React Hook useEffect 缺少对 redux 操作的依赖作为参数

React Hook useEffect has a missing dependency for redux action as parameters

我在这里发现了很多关于 React Hook useEffect 缺少依赖项 的类似问题。我已经检查过它们,但我没有找到我所面临的解决方案。我想将 redux thunk 函数 作为参数传递给 React 自定义钩子

下面是我的代码,运行良好。但是,我收到依赖项缺失警告,我不想添加 ignore warning eslint。如果我将 dispatchAction 添加到依赖数组列表,它会一次又一次地调度,因为 redux thunk asyn 函数已经完成、拒绝、挂起。

自定义挂钩

const useFetchData = (dispatchAction, page) => {
  const dispatch = useDispatch();
  const [loadMoreLoading, setLoadMoreLoading] = useState(false);
  const [errorMsg, setErrorMsg] = useState();

  useEffect(() => {
    const fetchData = async () => {
      setLoadMoreLoading(true);
      const resultAction = await dispatch(dispatchAction);
      if (resultAction.meta.requestStatus === 'rejected') {
        setErrorMsg(resultAction.payload.message);
      }
      setLoadMoreLoading(false);
    };
    fetchData();
  }, [dispatch, page]);

  return [loadMoreLoading, errorMsg]; // it is asking for adding dispatchAction.

我的组件

const SomeListing = ({userId}) => {
  const [page, setPage] = useState(1);
  const [loadMoreLoading, errorMsg] = useFetchData(
    fetchPropertyByUserId({userId: userId, page: page}),
    page,
  );
}

那么,有什么方法可以在 React 自定义钩子中添加 redux thunk 函数

如何从useEffect中提取fetch方法?:

  const fetchData = async () => {
    setLoadMoreLoading(true);
    const resultAction = await dispatch(dispatchAction);
    if (resultAction.meta.requestStatus === 'rejected') {
      setErrorMsg(resultAction.payload.message);
    }
    setLoadMoreLoading(false);
  };

  useEffect(() => {  
    fetchData();
  }, [fetchData]);

函数 fetchPropertyByUserId,当被调用时,即 fetchPropertyByUserId({userId: userId, page: page}),returns 一个“actionCreator”函数。

因此,当您在挂钩的第一个参数处调用此函数时 useFetchData,它每次都会 returns 一个新的“actionCreator”函数(我们知道每次调用挂钩渲染):

SomeListing.jsx:

const [loadMoreLoading, errorMsg] = useFetchData(
  fetchPropertyByUserId({userId: userId, page: page}), // <-- Here: it returns a new "actionCreator" function at call (render)
  page,
);

而且,一旦你把这个函数(钩子的第一个参数,即 dispatchAction)作为 useEffect 的依赖项,它应该会导致无限执行效果,因为,现在我们知道,dispatchAction 在每次渲染时都会被创建(因此,被更改)。

useFetchData.js:

export const useFetchData = (dispatchAction, page) => {

  // ...

  useEffect(() => {
    const fetchData = async () => {
      setLoadMoreLoading(true)
      const resultAction = await dispatch(dispatchAction)
      if (resultAction.meta.requestStatus === 'rejected') {
        setErrorMsg(resultAction.payload.message)
      }
      setLoadMoreLoading(false)
    }
    fetchData()
  }, [dispatch, dispatchAction, page]) // <-- "dispatchAction" added here

  // ...

如何解决?

传递一个 memoized actionCreator 函数:

SomeListing.jsx:

export const SomeListing = ({ userId }) => {
  const [page, setPage] = useState(1)

  // Here: "fetchPropertyByUserIdMemo" is memoized now
  const fetchPropertyByUserIdMemo = useMemo(
    () => fetchPropertyByUserId({ userId: userId, page: page }),
    [page, userId]
  )

  const [loadMoreLoading, errorMsg] = useFetchData(fetchPropertyByUserIdMemo, page)

  // ...
}