如何在反应中处理自定义挂钩的依赖项数组

How to handle dependencies array for custom hooks in react

我正在创建一个自定义挂钩并想定义一个可选参数,以便我可以在需要时传入额外的依赖项。我的代码类似于以下代码段:

import { useEffect } from 'react';

function useCustomHook(param1, extraDeps) {
  useEffect(() => {
    // do something with param1 here
  }, [param1, ...extraDeps])
}

react-hooks/exhaustive-deps 发出警告

React Hook useEffect has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies

有人知道如何解决该警告吗?或者将 deps 数组传递给自定义挂钩不是一个好习惯?

对于那些对为什么需要 extraDeps 感兴趣的人。这是一个例子:

const NewComponent = (props) => {
  [field1, setField1] = useState()
  [field2, setField2] = useState()

  // I only want this to be called when field1 change
  useCustomHook('.css-selector', [field1]);

  return <div>{field1}{field2}</div>;
}

您可以这样做:

将状态移动到您的自定义挂钩,运行 对其产生影响并 return 它。

类似于:

Component.js


function Component() {
  const [field,setField] = useCustomHook(someProps);
}

useCustomHook.js

import {useState, useEffect} from 'react';

function useCustomHook(props) {

  const [field,setField] = useState('');

  useEffect(()=>{
    // Use props received and perform effect after changes in field 1
  },[field1]);

  return([
    field,
    setField
  ]);
}

我认为问题在于您如何在自定义挂钩上创建依赖项数组。每次你这样做 [param1, ... extraDeps] 你都在创建一个新数组,所以 React 总是将它们视为不同的。

尝试将自定义挂钩更改为:

function useCustomHook(deps) {
  useEffect(() => {
    // do something with param1 here
  }, deps)
}

然后像

一样使用它
const NewComponent = (props) => {
  [field1, setField1] = useState()
  [field2, setField2] = useState()

  // I only want this to be called when field1 change
  useCustomHook(['.css-selector', field1]);

  return <div>{field1}{field2}</div>;
}

希望对您有所帮助!

我遇到了类似的问题,我希望在某些额外的依赖项发生更改时执行效果。
我没有设法提供这些额外的依赖关系,而是通过向调用者提供我希望执行的回调 并让他在需要时使用它来绕过

示例:

// This hook uses extraDeps unknown by EsLint which causes a warning
const useCustomEffect = (knowDep, extraDeps) => {

  const doSomething = useCallback((knownDep) => {/**/}, [])
  
  useEffect(() => {
    doSomething(knownDep)
  }, [doSomething, knownDep, ...extraDeps]) // Here there is the warning
}

//Instead of this, we give the caller the callback
const useCustomEffect = (knownDep) => {

  const doSomething = useCallback((knownDep) => {/**/}, [])
  
  useEffect(() => {
    doSomething(knownDep)
  }, [doSomething, knownDep]) // no more warning

  return { doSomething }
}

// Use it like this
const { doSomething } = useCustomEffect(foo)
useEffect(doSomething, [bar, baz]) // now I can use my callback for any known dependency

如果你想提供 extra-deps,你可以使用 useDeepCompareEffect 而不是 useEffect

https://github.com/kentcdodds/use-deep-compare-effect

您定义自定义挂钩的方式对我来说很有意义。我无法找到任何关于执行此操作的官方方法的文档,所以现在我的解决方案是禁用规则:

function useCustomHook(param1, extraDeps) {
  useEffect(() => {
    // do something with param1 here
  }, [param1, ...extraDeps]) // eslint-disable-line react-hooks/exhaustive-deps
}

我找到了一个有用的替代方案来替代这里提出的解决方案。如前所述 in this Reddit topic,React 团队显然推荐如下内容:

// Pass the callback as a dep
cost useCustomHook = callback => {
  useEffect(() => { /* do something */ }, [callback])
};

// Then the user wraps the callback in `useMemo` to avoid running the effect too often
// Whenever the deps change, useMemo will ensure that the callback changes, which will cause effect to re-run
useCustomHook(
  useMemo(() => { /* do something }, [a, b, c])
);

我已经使用过这种技术并且效果很好。