React useeffect 导致无限循环
2022-09-25
84
我是 React 的新手,正在创建一个自定义选择组件,该组件应该设置一个数组选定状态,同时触发 onchange 事件并将其与选定项一起传递给父级,同时获取初始值作为 prop 并设置一些数据。
let firstTime = true;
const CustomSelect = (props)=>{
const [selected, setSelected] = useState([]);
const onSelectedHandler = (event)=>{
// remove if already included in the selected items remove
//otherwise add
setSelected((prev)=>{
if (selected.includes(value)) {
values = prevState.filter(item => item !== event.target.value);
}else {
values = [...prevState, event.target.value];
}
return values;
})
// tried calling props.onSelection(selected) but its not latest value
}
//watch when the value of selected is updated and pass onchange to parent
//with the newest value
useEffect(()=>{
if(!firstTime && props.onSelection){
props.onSelection(selected);
}
firstTime = false;
},[selected])
return (<select onChange={onSelectedHandler}>
<option value="1"></option>
</select>);
};
我正在像这样的父级上使用它
const ParentComponent = ()=>{
const onSelectionHandler = (val)=>{
//do stuff with the value passed
}
return (
<CustomSelect initialValue={[1,2]} onSelection={onSelectionHandler} />
);
}
export default ParentComponent
上面的方法运行良好,但现在问题出现了,当我想通过更新选定状态将从父级传递的 initialValue 设置为 customSelect 时。我在 CustomSelect 上添加了以下内容,但它会导致无限循环
const {initialValue} = props
useEffect(()=>{
//check if the value of initialValue is an array
//and other checks
setSelected(initialValue)
},[initialValue]);
我知道我可以在 useState 中传递 initialValue,但我想在设置选定状态之前做一些检查。 我该如何解决这个问题,我还是 React 的新手。
2个回答
在您的
//使用传递的值进行操作
中,您很可能会更新组件父组件的状态,这会导致重新渲染父组件。传递 prop
initialValue={[1,2]
时,会在每次渲染时创建一个新的
[1,2]
数组实例,并导致 useEffect 上的无限渲染。为了解决这个问题,您可以将 initialValue prop 移动到其他地方作为 const 值,如下所示:
const INITIAL_VALUE_PROP = [1,2];
const ParentComponent = ()=>{
const onSelectionHandler = (val)=>{
//do stuff with the value passed
}
return (
<CustomSelect initialValue={INITIAL_VALUE_PROP} onSelection={onSelectionHandler}
/>
);
}
export default ParentComponent
Ahmet Emre Kilinc
2022-09-25
好的,发生这种情况的原因是您将
initialValue
属性作为数组传递,并且由于这是 JavaScript 中的引用值,这意味着每次传递(更新)时,都会传递不同的引用值/地址,因此效果将无限期地重新运行。解决此问题的一种方法是使用
React.useMemo
,
文档在这里
来存储/保留传递的数组的引用值,不会导致不必要的副作用运行。
Abdulrahman Ali
2022-09-25