【问题标题】:Should I include setState in useCallback's array of dependencies?我应该在 useCallback 的依赖数组中包含 setState 吗?
【发布时间】:2019-09-08 07:48:11
【问题描述】:
    const [active, setActive] = useState(false);

    const onActiveChanged = useCallback(
      isActive => () => {
        // do something
        setActive(isActive);
      },
      [setActive], // or just [] is okay?
    );

当同时使用useStateuseCallback(或useMemo)时,我是否应该在依赖项数组中包含setState

【问题讨论】:

  • @AngelSalazar useState 中的更新程序方法没有被记忆或没有保留相同的引用?
  • 我的错,根据文档“React 保证 setState 函数标识是稳定的,并且不会在重新渲染时改变。这就是为什么从 useEffect 或 useCallback 依赖列表中省略是安全的。”
  • @AngelSalazar 感谢您的确认!我还在github.com/reactjs/reactjs.org/blob/master/content/docs/… 中找到了那部分,所以只需传递一个空数组就可以了。您可以将其作为此问题的答案,或者我将发布我自己问题的答案。

标签: reactjs react-hooks


【解决方案1】:

React Docs - Hooks API Reference 上也有此建议。

setState 函数用于更新状态。它接受一个新的 状态值并将组件的重新渲染排入队列。

setState(newState);

在后续重新渲染期间,第一个值 useState 返回的将始终是最近的状态 应用更新。

注意

React 保证 setState 函数的身份是稳定的,不会 更改重新渲染。这就是为什么从 useEffect 中省略是安全的 或者 useCallback 依赖列表。

【讨论】:

    【解决方案2】:

    正如您正确暗示的那样,useCallback 的目的是memoise

    useCallback(fn, deps) 等价于 useMemo(() => fn, deps)。

    至于useMemo 的用途:

    您可以依赖 useMemo 作为性能优化,而不是语义保证。

    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

    但作为一项规则,useState 在渲染之间是稳定的(即预先记忆),因此您不需要再次记忆它

    那么问题来了,您的“做某事”是否低于昂贵的计算?使用useCallback 应该不会太麻烦,但很可能是你不需要的boilerplate code,几乎可以直接使用你的setActive 函数。

    const [active, setActive] = useState(false);
    
    const onActiveChanged = useCallback(
      isActive => () => {
        // do something
        setActive(isActive);
      },
      [setActive], // or just [] is okay?
    );
    
    

    在你的 useCallback 和其他钩子中防止不必要的依赖的另一种方法是使用functional updates。结果是你可以拥有这些:

    const [active, setActive] = useState(false);
    const [expensiveCalc, setExpensiveCalc] = useState(false);
    
    const onExpensiveCalc = useCallback(
      expensiveInput => () => {
        const newState = doExpensiveCalc(expensiveInput);
        expensiveCalc(newState);
      },
      [setActive], // here for completeness
    );
    
    return (<>
      // expensive calculation
      <button onClick={onExpensiveCalc}>Do lengthy calculation</button>
      // cheap calculation, using functional updates
      <button onClick={() => setActive(prevBoolean => !prevBoolean)}>Cheap Set Active</button>
    </>)
    
    

    请注意,设置状态在 onClick 中的工作方式与 nuance 有关,您应该使用箭头功能,因此您的 setActive 在单击时运行,而不是渲染。这在上面的第二个答案中显示,但没有解释。

    另见:What is useState() in React?

    【讨论】:

      猜你喜欢
      • 2010-09-18
      • 2022-11-06
      • 2016-01-29
      • 1970-01-01
      • 2021-09-29
      • 2023-01-16
      • 2019-12-01
      • 1970-01-01
      • 2018-11-19
      相关资源
      最近更新 更多