首页 > 解决方案 > 使用反应挂钩和上下文从 REST api 获取数据以进行状态管理的最佳方法?

问题描述

我正在尝试使用反应钩子和上下文 API 进行状态管理。我已经按照待办事项应用程序中的一些代码实现了一个 reducer 模式,但是现在我想开始定期从 API 获取数据(例如实现无限滚动),我现在不确定代码中的最佳位置在哪里进行这些 async-REST-api 调用。

我习惯于使用 redux 中间件库,如redux-observable,redux-thunk等来执行异步任务。但是现在我没有使用 redux,我不清楚进行异步更新的最佳方法是什么。我想我可以使用await-promise减速器,但这感觉不对。

有什么建议么?(在实现了 reducer 模式后,我很想回退到一个完整的 redux-with-redux-obnservable 实现,尽管我希望 context 可以精简所有样板。)

标签: reactjsreact-hooks

解决方案


这可能是我将如何实现它。我有一个标准减速器。我还将创建一个辅助功能组件来帮助我为我的上下文提供者设置值。

我还在源代码中做了一些注释。我希望下面的代码片段足够简单易懂。

    import React, { useReducer, useEffect, createContext } from 'react';
    import FetchService from './util/FetchService'; // some helper functions


    const OrderInfoContext = createContext();

    const reducer = (state, action) => {
      switch (action.type) {
        case 'init':
          return {};
        case 'changeData':
          return action.payload;
        default:
          return state;
      }
    };

    const changeData = data => ({
      type: 'changeData',
      payload: data
    });

    /**
     * This is a helper component that generate the Provider wrapper
     */
    function OrderInfoProvider(props) {
      // We will persist API payload in the state so we can assign it to the Context
      const [orders, dispatch] = useReducer(reducer, {});

      // We use useEffect to make API calls.
      useEffect(() => {
        async function fetchData() {
          /**
           * This is just a helper to fetch data from endpoints. It can be done using
           * axios or similar libraries
           */
          const orders = await FetchService
            .get('/api/orders');
          dispatch(changeData(orders))
        }
        fetchData();
      }, []);

      /**
       * we create a global object that is available to every child components
       */
      return <OrderInfoContext.Provider value={[orders, dispatch]} {...props} />;
    } 

    // Helper function to get Context
    function useOrderInfo() {
      const context = useContext(OrderInfoContext);
      if (!context) {
        throw new Error('useOrderInfo must be used within a OrderInfoProvider');
      }
      return context;
    }

    export { OrderInfoProvider, useOrderInfo , changeData }; 



推荐阅读