useEffect和依赖项数组

问题描述 投票:1回答:2

我试图了解useEffect如何处理对象。

这是一个示例,将帮助演示我的问题:

export function UseEffectHook() {
  const initialState = {
    firstName: "Joe",
    lastName: "Smith",
    address: {
      home: "123 street"
    }
  };
  const [user, setUser] = useState(initialState);
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("triggered");
  }, [user]);

  return (
    <div>
      <p>useEffect - Practice with different deps</p>
      {JSON.stringify(user)}
      <label>Firstname:</label>

      <input
        type="text"
        onChange={e => setUser({ ...user, firstName: e.target.value })}
      />
      <br />
      <label>Lastname:</label>
      <input
        type="text"
        onChange={e => setUser({ ...user, lastName: e.target.value })}
      />
      <button onClick={() => setCount(count + 1)}>Button</button>
   </div>
  );
}

我已经读过,由于在重渲染之间比较对象的方式,将对象作为依赖项放置在useEffect挂钩中不起作用。

我最初的想法是在此示例中单击按钮,并且更新计数还应导致useEffect挂钩被更新。情况并非如此,useEffect不会重新运行。

我无法找到足够人为的示例来帮助演示何时以及为何使用对象重新运行useEffect。任何帮助将不胜感激。

reactjs react-hooks
2个回答
1
投票

使用您的组件。

更改:

  • initialState移动到UseEffectHook之外。您不需要创建initialState每次重新渲染;
  • 使用useCallback将返回回调的记忆版本,仅在其中一个依赖项已更改时才更改;
  • [setUsersetCountupdater function;
  • handleOnChangeUser能够用于用户对象的所有字段。每次handleOnChangeUser-创建对用户对象的新引用。在这种情况下,useEffect能够检测到更改;

import React, { useCallback, useEffect, useState } from 'react';

const initialState = {
  firstName: "Joe",
  lastName: "Smith",
  address: {
    home: "123 street",
  }
};

export function UseEffectHook() {
  const [user, setUser] = useState(initialState);
  const [count, setCount] = useState(0);
  const handleOnChangeUser = useCallback((event) => {
    const { name, value } = event;
    
    setUser(prevState => ({ ...prevState, [name]: value }));
  }, []);
  
  const increaseCount = useCallback(() => {
    setCount(prevState => prevState + 1);
  }, []);

  useEffect(() => {
    console.log("triggered");
  }, [user]);

  return (
    <div>
      <p>useEffect - Practice with different deps</p>
      {JSON.stringify(user)}

      <label>
        <span>Firstname:</span>

        <input
          type="text"
          name="firstName"
          onChange={handleOnChangeUser}
        />
      </label>
      
      <br />
      
      <label>
        <span>Lastname:</span>
        
        <input
          type="text"
          name="lastName"
          onChange={handleOnChangeUser}
        />
      </label>

      <button onClick={increaseCount}>Increase</button>
   </div>
  );
}

1
投票

useEffect将在其依赖项数组中的任何对象更改引用时重新运行。

例如,在您的代码中,在调用setUser之前,用户始终是稳定的,在这种情况下,它将更改为新引用并在该位置运行。

如果改为在每个渲染中将用户定义为一个新对象,则useEffect将在每次重新渲染组件时运行。

  const user = {
    firstName: 'Joe',
    lastName: 'Smith',
    address: {
      home: '123 street',
    },
  };

全部涉及参照相等性。每个渲染器上是否为previousUser === newUser。对于依赖数组中的每个变量,React本质上都执行与检查(我相信Object.is)非常相似的检查。

© www.soinside.com 2019 - 2024. All rights reserved.