Reactjs React路由器/Redux应用中的数据/模型管理

Reactjs React路由器/Redux应用中的数据/模型管理,reactjs,data-structures,redux,data-management,Reactjs,Data Structures,Redux,Data Management,我想知道在使用React-Router和Redux的React应用程序中加载服务器数据的最佳方法是什么。 例如:访问/dossier/123时,我只想检索该特定档案的数据。导航到/档案时,我希望显示有关所有项目的“部分”数据(标题、说明、所有者等)。 这意味着,我的模型看起来像这样: { dossiers: IDossier[]; } interface IDossier { id: number; title: string; description: str

我想知道在使用
React-Router
Redux
的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: { ... }
    }]
}
但是,在输入at/档案时,初始状态看起来更像

{
    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 });
        }
      }
    },
  };
};
然后为您拥有的每个集合创建loader

const dossiersLoader = createCollectionLoader(store, state => state.dossiers, 'DOSSIERS');
最后,每次您想要确保档案(或单个档案已加载)时,调用适当的加载程序函数

dossiersLoader.loadAll();
// or
dossiersLoader.load(id)
为了使它更好,引入一个表示工作单元的抽象——称之为任务、作业、过程、传奇等等


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

感谢@jokka的解释。虽然我希望有一些更通用的模式,而不是
//决定是否加载
部分:),但很难概括关于数据刷新的实际决定,因为在整个应用程序中它变化很大-取决于,例如,你是否有显式刷新按钮,数据是否变化迅速等等,听起来你已经对逻辑下了决心。问题是什么?你应该跳过加载还是怎么做?