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

时间:2020-02-25 13:23:24

标签: reactjs react-hooks use-effect

所以我对useEffect依赖项有疑问

这是来自react docs:

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]。如果我们看一下前面的示例,这两个结果都将为true,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之类的动态属性作为依赖项吗?

1 个答案:

答案 0 :(得分:1)

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"

React是否跟踪...值或...引用?

真的没有对他们中的任何一个“保持跟踪”。它只会检查与上一个呼叫的区别,而忽略其他所有内容。

我可以使用动态属性作为依赖项吗?

是的,您可以(因为它们不像您想象的那样“动态”)

那么正确的方法是什么?

最好不要考虑发生什么反应魔术,但是

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

然后,您的“动态特性” 成为 “在一个函数调用期间的常量”。 。无论哪个变量动态变化以及如何动态变化,上次总是一个值,现在总是一个值。

说明:

这里重要的“诀窍”是,该组件只是一个javascript函数,称为 “任何可能发生更改的地方” ,因此{{ 1}}也被调用(因为useEffect()只是组件内部的函数调用)。
并非总是仅调用传递给useEffect的回调函数。

useEffect()不会渲染组件,useEffect被称为何时调用组件,然后仅调用赋予它的函数是否有效,这取决于依赖项数组中的任何值是否与上次调用useEffect()的值不同。

如果在给useEffect的函数中对状态或状态进行了任何更改(使React认为必须重新渲染的任何内容),则

React 可能重新渲染组件。状态更改的原因,无论它来自何处,都不是因为useEffect调用。

示例:

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函数。
    (不变的selectedEmployee不变!)
  • setSelectedEmployee( newValue )被再次调用。
    (这是一个新的函数调用。所有常量都消失了!只有React在后台存储一些状态。)
  • MyComponent()被调用,结果存储在新的常量useState()中。
  • selectedEmployee被调用,并根据useEffect()的先前值和当前值来决定是否应调用其回调。
    如果未调用该回调并且未进行任何其他更改,则您可能根本不会注意到发生了任何事情。
  • selectedEmployee已呈现。