React Router / Redux应用程序中的数据/模型管理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Router / Redux应用程序中的数据/模型管理相关的知识,希望对你有一定的参考价值。

我想知道在使用React RouterRedux的React应用程序中加载服务器数据的最佳方法是什么。例如:访问/dossier/123时,我只想检索该特定档案的数据。导航到/档案时,我想显示有关所有项目(标题,描述,所有者......)的“一些”数据。这意味着,我的模型看起来像这样:

{
    dossiers: IDossier[];
}

interface IDossier {
    id: number;
    title: string;
    description: string;
    owner: IUser;
    codes?: ICode[];
    template?: ITemplate;
}

当在“/ dossier / 123”中“输入”应用程序时,“初始”状态看起来像

{
    dossiers: [{
        id: 123,
        title: "My dossier",
        description: "...",
        owner: { id: 1; name: "John Doe" },
        codes: [{ ... }, { ... }],
        template: { ... }
    }]
}

然而,当进入/档案时,初始状态看起来更像

{
    dossiers: [{
        id: 123,
        title: "My dossier",
        description: "...",
        owner: { id: 1; name: "John Doe" }
    }, {
        id: 456,
        title: "Another dossier",
        description: "...",
        owner: { id: 2; name: "Jane Doe" }
    }, {
        ...
    }]
}

当导航到/ dossier / 123或/ dossier / 456时,我需要某种指示我必须加载代码和模板信息,因为它们尚未被提取 - 至少不是我第一次进入url端点。

所以我想我的主要问题是:如何在应用程序中来回导航时,如何在商店中已经可用时重新获取数据,从而以健壮的方式管理它。

答案

每次需要加载某个档案实例或整个集合时,您应首先查看商店中已有的数据,并确定是否需要调用API。由你来决定。有些应用可能会在每次打开页面时刷新数据,有些应用程序最多每天刷新一次。

如果存在多个具有相同逻辑的不同数据集合 - 例如,具有id的对象的数组,这些对象首先被加载并且从不刷新 - 那么您应该对该逻辑进行抽象,这样您就不需要重复一遍。

我建议使用函数式编程。更精确,更高阶的功能。

例如,创建一个通用的集合加载器。

// Collection loader “constructor”.
const createCollectionLoader = (store, selector, actionPrefix) => {
  // Actual collection loader.
  return {
    // Function that makes sure collection is loaded.
    loadAll: () => {
      const collection = selector(store.getState());
      const shouldLoad = …; // Decide if it should load.
      if (shouldLoad) {
        store.dispatch({ type: `${actionPrefix}_LOAD`, data });
        try {
          const data = …; // Load.
          store.dispatch({ type: `${actionPrefix}_LOAD_SUCCESS`, data });
        } catch (error) {
          store.dispatch({ type: `${actionPrefix}_LOAD_ERROR`, error });
        }
      }
    },
    // Function that makes sure single collection item is loaded.
    load: (id) => {
      const collection = selector(store.getState());
      const item = collection.find(item => item.id === id);
      const shouldLoad = …; // Decide if it should load.
      if (shouldLoad) {
        store.dispatch({ type: `${actionPrefix}_ITEM_LOAD`, data });
        try {
          const data = …; // Load.
          store.dispatch({ type: `${actionPrefix}_ITEM_LOAD_SUCCESS`, data });
        } catch (error) {
          store.dispatch({ type: `${actionPrefix}_ITEM_LOAD_ERROR`, error });
        }
      }
    },
  };
};

然后为您拥有的每个集合创建加载器。

const dossiersLoader = createCollectionLoader(store, state => state.dossiers, 'DOSSIERS');

最后,每次要确保档案(或单个档案被加载)时,请调用足够的装载程序功能。

dossiersLoader.loadAll();
// or
dossiersLoader.load(id)

为了使它更好,引入代表工作单元的抽象 - 称之为任务,工作,流程,传奇等。

我更喜欢将我的React Web应用程序代码拆分为三个不同的组:UI,状态,逻辑。为此,我建议分别使用react(显然),react-reduxredux-saga。看到许多高阶组件,传奇,甚至减速器并不罕见。

以上是关于React Router / Redux应用程序中的数据/模型管理的主要内容,如果未能解决你的问题,请参考以下文章

在 react + redux + react-router-redux 中导航到用户登录成功的主页

在 React-Redux-Router 中避免使用 Concat URL

使用 Redux-Router + React-Router 将基本 URL 添加到应用程序

如何用 redux 和 react-router 组织状态?

react-router-redux 打破了我的应用程序状态

混淆 react-router-dom 和 react-router-redux