我是React的新手,对功能组件的生命周期感到非常困惑。 假设我有许多类型的输入:复选框,a,b,c和d。它们的值分别是a,b,c和d。
const OnBoarding = () => {
const [isChecked, setIsChecked] = useState({
a: false,
b: false,
c: false,
d: false
});
const [allCheckedItems, setAllCheckedItems] = useState([]);
//Write function that pushes checked value to state array when clicked
const onChecked = e => {
setIsChecked({
...isChecked,
[e.target.value]: e.target.checked
});
const all = Object.keys(isChecked).filter(function(key){
return isChecked[key] === true;
});
console.log("all items that are TRUE : " + all);
setAllCheckedItems([all]);
console.log("allCheckedItems : " + allCheckedItems);
};
useEffect(() => {
console.log(isChecked);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
我有一个功能组件,其状态为类型为对象的状态,具有许多属性,所有布尔值,如下所示:
const [isChecked, setIsChecked] = useState({
a: false,
b: false,
c: false,
d: false
})
我还有一个其他状态,它是 array ,我们称之为 allCheckedItems ,它应该是 isChecked的所有键的数组 strong>设置为true。
const [allCheckedItems, setAllCheckedItems] = useState([]);
通过一个功能onChecked,当复选框被选中,它的值在在器isChecked 对象集为真
我调用useEffect(),在其中编写了一个过滤器函数来过滤所有正确的属性。所有设置为true的属性都存储在名为“ all” 的数组中。
我的问题出在我必须更新数组 allCheckedItems 的状态时。如果我写在useEffect钩子中:
setAllCheckedItems([all]);
我遇到无限循环。如果我在 onChecked函数中编写它,则每当我单击一个复选框时,我在控制台中登录的allCheckedItems的状态就会一键显示。 就像,我单击以选中“ a”,它记录:
[]
然后我单击“ b”,它记录:
[a]
然后单击“ c”,它记录:
[a, b]
我希望当我选中一个框时,两个状态都会更新,并且allItemsChecked会立即记录所有已检查的项目... 有人可以向我解释这种行为吗?几天来,这让我头疼。
答案 0 :(得分:2)
useEffect
挂钩给您带来无限循环的原因是,在每次渲染未提供第二个参数时,都会在每个渲染之后触发useEffect。官方的react documentation中有针对react钩子的声明,如果第二个参数中的值未更改,则组件将跳过效果的应用。
如果我们将setAllCheckedItems()
设置为useEffect()
的第二个参数,则在[isChecked]
内调用useEffect()
可以正常工作(这将确保仅当isChecked
的值已更改)
useEffect(() => {
setAllCheckedItems([all]);
}, [isChecked]);
我建议您通过在复选框的setAllCheckedItems()
事件中调用onClick
来降低代码的复杂性,因为每次选中复选框时都会运行该代码。您可以重构onChecked
方法,以使setAllCheckedItems()
不依赖于isChecked
状态。
const onChecked = (e) => {
// get current checked state, and update it with the checkbox values
const updatedChecked = {
...isChecked,
[e.target.value]: e.target.checked
}
// update isChecked state
setIsChecked(updatedChecked);
const all = Object.keys(updatedChecked).filter(function(key){
return updatedChecked[key] === true;
});
// update allCheckedItems state
setAllCheckedItems([all]);
}
如您所见,我们已经创建了isChecked
状态的副本,并使用新值更新了该副本。此外,我们使用该副本返回已检查的密钥。之后,我们更新各自的状态。