【问题标题】:React Hook useEffect has a missing dependency for redux action as parametersReact Hook useEffect 缺少将 redux 操作作为参数的依赖项
【发布时间】:2021-07-28 10:00:19
【问题描述】:

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

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

【问题讨论】:

    标签: reactjs react-hooks redux-thunk


    【解决方案1】:

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

    因此,当您在钩子useFetchData 的第一个参数位置调用此函数时,它每次都会返回一个新的“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
    
      // ...
    

    如何解决?

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

    【讨论】:

    • 很好的解释
    【解决方案2】:

    从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]);
    

    【讨论】:

    猜你喜欢
    • 2021-02-23
    • 2019-10-24
    • 2020-10-26
    • 2020-03-07
    • 2020-02-25
    • 2020-06-11
    • 2020-03-30
    • 2020-12-29
    • 2019-09-20
    相关资源
    最近更新 更多