useEffect在状态更改后未触发

时间:2020-07-16 20:55:00

标签: reactjs use-effect use-state

我正在创建一个自定义下拉列表,该列表允许在下拉列表中推送新项目。由于某种原因,useEffect不会在状态更改时触发,但会在初始渲染时触发。我很确定我缺少一些小东西,但是看不到。当用户单击与“ addNewOptionToTree”方法绑定的按钮时,应推送新项目。然后categoryList应该在下拉列表中显示新项目。控制台日志被触发并且出现了新的arr ...有什么想法吗?

高于退货:

    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);
    
      }

在返回块中:

<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>

3 个答案:

答案 0 :(得分:2)

您的情况不会更改,因为您objectsarrays在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将被触发。

答案 1 :(得分:0)

问题是您正在使用数组比较并触发useEffect,因此当数组长度更改时,它将在初始渲染时触发,但是如果长度相同并且仅更改任何元素,则在后续更改时触发,这不会触发useEffect

您可以使用JSON.stringify

useEffect(() => {
        console.log("categoryList::::::::::::::::", categoryList)
      }, [JSON.stringify(categoryList)]);

答案 2 :(得分:0)

只是改变

const categoryListArr = categoryList
categoryListArr.push(newOption)
setCategoryList(categoryListArr)

setCategoryList([...categoryList, newOption]);

这将更改Array引用并触发效果。