首页 > 解决方案 > React Hook useEffect 缺少将 redux 操作作为参数的依赖项

问题描述

我在这里发现了许多关于React Hook useEffect has a missing dependency 的类似问题。我已经检查过它们,但我没有找到我所面临的解决方案。我想将redux thunk 函数作为参数传递给React custom hook

下面是我的代码,它工作正常。但是,我得到了依赖缺失警告,我不想添加忽略警告 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 功能?

标签: reactjsreact-hooksredux-thunk

解决方案


该函数fetchPropertyByUserId在调用 iefetchPropertyByUserId({userId: userId, page: page})时返回一个“actionCreator”函数。

因此,当您在 hook 的第一个参数的位置调用此函数时useFetchData,它每次都会返回一个新的“actionCreator”函数(我们知道在每次渲染时都会调用 hooks):

SomeListing.jsx 中:

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

而且,一旦您将此函数(钩子的第一个参数,即 ie 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

  // ...

如何解决?

传递一个记忆化的 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)

  // ...
}

推荐阅读