React useEffect仅在页面加载后修改代码才生效,Autocomplete列表异常
问题根因
- useEffect依赖配置错误:你将useEffect的依赖数组设为空,还关闭了依赖检查,导致该逻辑仅在组件首次挂载时执行一次。如果父组件的
newListState.words是异步加载的,首次挂载时数据还未返回,useEffect拿到的就是空数组,后续父组件数据更新后也不会重新触发useEffect执行。你手动修改代码触发热重载时,组件重新挂载,此时newListState.words已经有数据,所以看起来功能正常了。 - 状态突变未触发重渲染:Autocomplete的onChange回调里,你直接修改了props传入的
newListState.selected属性,React状态要求不可变更新,直接修改原对象不会触发组件重渲染,所以选中操作看起来没生效,只有热重载触发组件重渲染时才会显示你修改后的值。 - 代码冗余错误:useEffect里临时数组名和state重名,且setState时错误展开了数组,属于不必要的代码问题。
修复方案
import React, { useState, useEffect } from 'react' import { makeStyles } from '@material-ui/core/styles' import Checkbox from '@material-ui/core/Checkbox' import TextField from '@material-ui/core/TextField' import Autocomplete from '@material-ui/lab/Autocomplete' import Typography from '@material-ui/core/Typography' import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank' import CheckBoxIcon from '@material-ui/icons/CheckBox' const icon = <CheckBoxOutlineBlankIcon fontSize='small' /> const checkedIcon = <CheckBoxIcon fontSize='small' /> const useStyles = makeStyles((theme) => ({ root: { margin: 'auto' }, paper: { width: 250, height: 230, overflow: 'auto', backgroundColor: '#bdbdbd' }, button: { margin: theme.spacing(0.5, 0) }, checkbox: { color: '#FFF342' }, textfield: { backgroundColor: '#bdbdbd' } })) const WordSelect = ({ newListState, setNewListState }) => { const classes = useStyles() const [wordsText, setWordsText] = useState({ wordOptions: [] }) // 把newListState.words加入依赖数组,数据更新时重新执行逻辑 useEffect(() => { const options = newListState.words.map(x => x.text) // 去掉不必要的数组展开操作 setWordsText({ wordOptions: options }) }, [newListState.words]) return ( <> <Autocomplete multiple id='checkboxes-tags-demo' disableCloseOnSelect value={newListState.selected} options={wordsText.wordOptions} getOptionLabel={(option) => option} getOptionSelected={(option, value) => option === value} onChange={(event, newValue) => { // 调用setNewListState做不可变更新,触发组件重渲染 setNewListState(prev => ({ ...prev, selected: newValue })) }} renderOption={(option, { selected }) => ( <> <Checkbox className={classes.checkbox} icon={icon} checkedIcon={checkedIcon} style={{ marginRight: 8 }} checked={selected} /> <Typography className={classes.checkbox}> {option} </Typography> </> )} style={{ width: 500 }} renderInput={(params) => ( <TextField {...params} className={classes.textfield} variant='outlined' placeholder='Select Words' /> )} /> </> ) } export default WordSelect
内容的提问来源于stack exchange,提问作者Pat Downer
相关产品推荐
相关产品推荐

