React Hooks:在useEffect挂钩中引用上下文并管理依赖项

时间:2019-09-15 14:16:30

标签: javascript reactjs react-hooks use-effect

我正在尝试使用react挂钩制作一个Table组件,该组件根据用户可以选择的一组过滤器显示API中的数据行。我想每当用户单击“应用过滤器”按钮时都发出一个新的调用来提取数据,而当用户对过滤器进行更改时,则单击不是

我正在使用上下文来管理“过滤器”状态和“ lastFetched”状态,该状态跟踪用户最后一次单击“应用过滤器”按钮的时间(以及页面上的其他状态)。通过useReducer挂钩及其派发方法(请参见here)对上下文进行更新。

数据获取发生在useEffect挂钩中,只要'lastFetched'状态更改,该挂钩就会重新运行。这似乎工作正常。但是,效果引用了上下文中未包含在依赖项中的其他值(即过滤器)。我知道详尽无遗的eslint规则,并且担心我没有正确处理该钩子的依赖项。

const Table = () => {
    const [context, dispatch] = useTableContext(); // implemented with createContext and useReducer
    const { filters, lastFetched } = context;

    useEffect(() => {
        if (!filters.run) {
            return;
        }

        dispatch({ type: 'FETCH_DATA_BEGIN' });
        const params = convertContextToParams(context); // this is lazy, but essentially just uses the the filters and some other state from the context 

        API.fetchData(params)
            .then((data) => {
                dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data.results });
            })
            .catch((e) => {
                dispatch({ type: 'FETCH_DATA_FAILURE', payload: e.response.data.message });
            });

        return () => { ... some cleanup... }; 
    }, [lastFetched]); // <== This is the part in question

 return <...some jsx.../>
};

再次,这似乎是可行的,但是根据react docs,看来我应该在钩子的依赖项中包括钩子中使用的上下文中的所有值,以防止陈旧的引用。这将导致逻辑​​中断,因为我不想在过滤器发生更改时就获取数据。

我的问题是:当用户单击“应用过滤器”,更新context.lastFetched并触发useEffect钩子时,该钩子是否会从上下文中引用过时的过滤器状态?如果是这样,为什么?由于只要单击按钮就可以重新运行效果,并且所有状态更新都通过reducer完成,因此在闭包中引用陈旧变量的通常危险是否仍然适用?

任何指导表示赞赏!

注意:我已经考虑过使用useRef来防止此问题,或者可能是设计一些自定义异步中间件来在某些调度上获取数据,但这是我目前的解决方案。

1 个答案:

答案 0 :(得分:0)

我不是专家,但我想提供我的看法。根据我对Context如何工作的理解,当前的实现不会使您获得过时的过滤器数据。 useReducer用新对象更新状态,该对象将触发Table重新渲染。

此外,Table组件实际上并不关心过滤器数据,除非lastFetched被click事件更改。如果lastFetched被更改,则TableContext的所有使用者将再次被重新渲染。您也不应获取过时的过滤器数据。