在 useEffect 中使用 redux action 的最佳方法是什么?

IT技术 reactjs redux react-redux
2021-05-12 11:09:33

我有一个如下所示的 React 组件(省略了某些部分),并且我正在使用 redux 进行状态管理。getRecentSheets操作包含一个 AJAX 请求,并将响应分派给 redux,reduxstate.sheets.recentSheets使用响应的数据进行更新

所有这些都按预期工作,但是在构建它时会抛出关于useEffect 缺少依赖项的警告: 'getRecentSheets'但是,如果我添加getRecentSheets到 useEffect 的依赖项数组,它将开始无限期地重新运行,从而冻结应用程序。

我已经阅读了关于useEffect钩子的React 文档https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies但它没有t 为此类用例提供了一个很好的例子。我想它与 useCallback 或 react-redux useDispatch 有关,但没有示例,我不确定如何实现它。

有人可以告诉我在 useEffect 中使用 redux action 的最简洁和惯用的方法是什么,以及如何避免有关缺少依赖项的警告?

import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import SheetList from '../components/sheets/SheetList';
import { getRecentSheets } from '../store/actions/sheetsActions';

const mapStateToProps = (state) => {
    return {
        recentSheets: state.sheets.recentSheets,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        getRecentSheets: () => dispatch(getRecentSheets()),
    }
}

const Home = (props) => {
    const {recentSheets, getRecentSheets} = props;

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

    return <SheetList sheets={ recentSheets } />
};

export default connect(mapStateToProps, mapDispatchToProps) (Home);
3个回答

毕竟,似乎正确的方法如下:

// ...
import { useDispatch } from 'react-redux';
import { getRecentSheets } from '../store/actions/sheetsActions';

const Home = props => {
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(getRecentSheets());
    }, [dispatch])

    // ...
};

这样它就不会抱怨getRecentSheets缺少依赖项数组。正如我从阅读 React doc on hooks 中了解到的那样,这是因为它没有在组件内部定义。虽然我是前端新手,但我希望我没有在这里搞砸。

我会添加一个检查以查看是否recentSheets存在,并将其用作我的依赖项。

useEffect(() => {
    if (!recentSheets) getRecentSheets();
}, [recentSheets])

在你的钩子中传递一个空数组告诉 React 你的钩子函数不会有任何来自 props 或 state 的依赖值。

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

当您将调度程序声明为钩子的依赖项时,就会出现无限循环。当组件初始化时,props.recentSheets尚未设置,并且在您进行 AJAX 调用后将重新呈现。

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

你可以尝试这样的事情:

const Home = ({recentSheets}) => {
    const getRecentSheetsCallback = useCallback(() => {
       getRecentSheets();
    })

    useEffect(() => {
        getRecentSheetsCallback();
    }, [recentSheets]) // We only run this effect again if recentSheets changes


    return <SheetList sheets={ recentSheets } />
};

无论 Homes 重新渲染多少次,您都会在调度调用中保留记忆功能。

或者,您可能遇到过利用本地状态找到类似模式,然后使您的效果“依赖”于sheets.

const [sheets, setSheets] = useState(recentSheets)

希望这可以帮助