状态更改后 useEffect 未触发
useEffect not getting trigger after state change
我正在制作一个自定义下拉菜单,它允许在下拉菜单中推送新项目。由于某种原因,useEffect 不会在状态更改时触发,而是在初始渲染时触发。我很确定我错过了一些小东西,但看不到它。当用户单击绑定到 'addNewOptionToTree' 方法的按钮时,应推送新项目。然后 categoryList 应该在下拉列表中显示新项目。控制台日志被触发,新的 arr 出现了……有什么想法吗?
以上 return:
const [newOption, setNewOption] = useState('')
const [categoryList, setCategoryList] = useState(["Calendars", "Meetings", "Apostrophes work!"])
useEffect(() => {
console.log("categoryList::::::::::::::::", categoryList)
}, [categoryList]);
function addNewOptionToTree() {
console.log('category:', categoryList);
console.log('newOption:', newOption);
const categoryListArr = categoryList
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
console.log("category:", categoryListArr);
}
在return块中:
<div className='dropDownList'>
<div className='listItem' key={'add-item-key'}>
<Input
type='text'
label=''
value={newOption}
placeholder='Add New Category'
onChange={val => setNewOption(val)}
/>
<div className='icon-add-contain dropdown-add-btn' onClick={addNewOptionToTree}></div>
</div>
{
categoryList.length > 0 &&
categoryList.map((category, index) => (
<div className='listItem' onClick={onOptionClicked(category)} key={'level1-'+index}>
{category}
</div>
))
}
</div>
你的情况没有改变,因为你 objects
和 arrays
在 JS 中是通过引用而不是值进行比较的。
例如
let foo = {bar: 1}
let faz = foo
let notFoo = {bar: 1}
foo === faz // true
foo === notFoo // false
话虽这么说,在这里:
const categoryListArr = categoryList // you are passing categoryList by reference
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
你在直接变异你的状态,这通常不好。为了使其正常工作,您需要以不可变的方式创建 categoryListArr
数组
const categoryListArr = [...categoryList] // this is a new array, which contains the same items from the state
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
现在你的 useEffect
将被触发。
问题是您正在使用数组来比较和触发 useEffect,因此它会在初始渲染时触发,因为数组的长度发生变化,但如果长度相同并且只有任何元素发生变化,则在后续更改时触发,这不会触发 useEffect
您可以使用JSON.stringify
useEffect(() => {
console.log("categoryList::::::::::::::::", categoryList)
}, [JSON.stringify(categoryList)]);
改变一下
const categoryListArr = categoryList
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
在
setCategoryList([...categoryList, newOption]);
这将更改数组引用并触发效果。
我正在制作一个自定义下拉菜单,它允许在下拉菜单中推送新项目。由于某种原因,useEffect 不会在状态更改时触发,而是在初始渲染时触发。我很确定我错过了一些小东西,但看不到它。当用户单击绑定到 'addNewOptionToTree' 方法的按钮时,应推送新项目。然后 categoryList 应该在下拉列表中显示新项目。控制台日志被触发,新的 arr 出现了……有什么想法吗?
以上 return:
const [newOption, setNewOption] = useState('')
const [categoryList, setCategoryList] = useState(["Calendars", "Meetings", "Apostrophes work!"])
useEffect(() => {
console.log("categoryList::::::::::::::::", categoryList)
}, [categoryList]);
function addNewOptionToTree() {
console.log('category:', categoryList);
console.log('newOption:', newOption);
const categoryListArr = categoryList
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
console.log("category:", categoryListArr);
}
在return块中:
<div className='dropDownList'>
<div className='listItem' key={'add-item-key'}>
<Input
type='text'
label=''
value={newOption}
placeholder='Add New Category'
onChange={val => setNewOption(val)}
/>
<div className='icon-add-contain dropdown-add-btn' onClick={addNewOptionToTree}></div>
</div>
{
categoryList.length > 0 &&
categoryList.map((category, index) => (
<div className='listItem' onClick={onOptionClicked(category)} key={'level1-'+index}>
{category}
</div>
))
}
</div>
你的情况没有改变,因为你 objects
和 arrays
在 JS 中是通过引用而不是值进行比较的。
例如
let foo = {bar: 1}
let faz = foo
let notFoo = {bar: 1}
foo === faz // true
foo === notFoo // false
话虽这么说,在这里:
const categoryListArr = categoryList // you are passing categoryList by reference
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
你在直接变异你的状态,这通常不好。为了使其正常工作,您需要以不可变的方式创建 categoryListArr
数组
const categoryListArr = [...categoryList] // this is a new array, which contains the same items from the state
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
现在你的 useEffect
将被触发。
问题是您正在使用数组来比较和触发 useEffect,因此它会在初始渲染时触发,因为数组的长度发生变化,但如果长度相同并且只有任何元素发生变化,则在后续更改时触发,这不会触发 useEffect
您可以使用JSON.stringify
useEffect(() => {
console.log("categoryList::::::::::::::::", categoryList)
}, [JSON.stringify(categoryList)]);
改变一下
const categoryListArr = categoryList
categoryListArr.push(newOption)
setCategoryList(categoryListArr)
在
setCategoryList([...categoryList, newOption]);
这将更改数组引用并触发效果。