我可以在 useEffect 的依赖数组中使用动态属性吗?

Can I use dynamic properties in dependency array for useEffect?

所以我有一个关于 useEffect 依赖项的问题

这是来自反应文档:

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes

这到底是什么意思,React 是跟踪 count 变量及其值,并在值更改时做出反应,还是 React 跟踪数组中的第一个元素及其值。

这是什么意思?让我解释更多。所以如果我们有这样的 [name] 作为依赖项。在计算时,数组可能会产生 ['Bob']['Steve']。显然这是一个更改,useEffect 将重新渲染组件。但是它是如何检查的呢?

它是跟踪 name 还是跟踪 dependencyArray[0]。如果我们看一下前面的示例,这两个结果都会为真,namefirst element 都将它们的值从 'Bob' 更改为 'Steve'。但它实际上是如何工作的?

目前在我的代码中,我正在使用类似 [employees[selectedEmployee].name] 的东西,其中 selectedEmployee 是 UI 上可点击的东西,它变成 'Bob' 或 'Steve'

例如:

const employees = {
   Bob: {
      name: 'Bob'
   },
   Steve: {
      name: 'Steve'
   }
}

这意味着最后,在求值时,依赖数组的结果仍然是 ['Bob'] --> ['Steve'],如果 React 正在求值 dependencyArray[0] 那么它有显然已更改并且组件应该重新呈现,但如果它跟踪引用,那么我将完全更改引用,这可能会导致问题。

那么正确的做法是什么?我可以使用像 employees[selectedEmployee].name 这样的动态属性作为依赖项吗?

count 是一个值,不是引用。

它只是旧的 Javascript,没有什么花哨的:

const myArray = [ count ]; // new array containing the value of variable 'count'
const myFunction = () => {
  document.title = `You clicked ${count} times`;
}

useEffect(
  myFunction,
  myArray
);

// Means actually:
// "Run this function if any value in the array
// is different to what it was last time this useEffect() was called"

does React keep track of the ... value, or ... the reference ?

React 真的'keep track'其中任何一个。它只检查 与上一次调用 的差异,而忽略其他所有内容。

Can I use dynamic properties as a dependency?

是的,你可以(因为它们不像你想象的那样'dynamic')

So what's the correct approach?

最好少考虑任何正在发生的反应魔法,但是

  • 理解组件是一个函数,相信 React 会在必要时调用它并且
  • 从一个普通的Javascript角度考虑其中使用的变量(属性和状态)。

那么你的'dynamic properties'就变成了'constant variables during one function call'。无论哪些变量动态变化,如何变化,总是上次一个值,现在一个值。

解释:

这里重要的 'trick' 是,组件只是一个 javascript 函数,调用方式类似于 'whenever anything might have changed',因此 useEffect() 也被调用(因为 useEffect() 只是组件内部的函数调用)。
只是传递给useEffect的回调函数并不总是被调用。

useEffect 渲染组件,useEffect 被调用 组件被调用时,并且然后只调用给它的函数,或者不调用,这取决于 dependencies 数组中的任何值是否与上次调用 useEffect() 时的值不同。

React 可能 重新渲染组件,如果在给 useEffect 的函数中对状态或其他东西做了任何更改(任何让 React 认为它必须重新渲染的东西),但这是状态变化的结果,无论它来自哪里,而不是因为 useEffect 调用。

示例:

const MyComponent = (props) => {

  // I'm assigning many const here to show we are dealing with local constants.
  // Usually you would use this form (using array destructuring):
  // const [ selectedEmployee, setSelectedEmployee ] = useState( someInitialValue );

  const myStateValueAndSetter = useState( 'Bob' );
  const selectedEmployee    = myStateValueAndSetter[0];
  const setSelectedEmployee = myStateValueAndSetter[1];

  const employees = {
    Bob: { name: 'Bob' },
    Steve: { name: 'Steve' }
  };

  const currentName = employees[ selectedEmployee ].name;

  useEffect(() => {
    document.title = 'current name: ' + currentName;
  }, [ currentName ]);

  return <MyClickableComponent onClick={( newValue ) => {
    setSelectedEmployee( newValue )
  }}>;
};
  • 点击 MyClickableComponent 调用当前 setSelectedEmployee( newValue ) 函数。
    (常量 selectedEmployee 没有改变!)
  • MyComponent()又被调用了
    (这是一个新的函数调用。所有的常量都没有了!只有 React 在后台存储一些状态。)
  • useState()被调用,结果存储在一个新常量selectedEmployee.
  • useEffect() 被调用,并根据 selectedEmployee.
    的先前和当前值决定是否调用其回调 如果没有调用回调并且没有其他任何更改,您可能根本不会注意到发生了什么。
  • <MyClickableComponent ... /> 被渲染。