Redux - 管理预加载状态

时间:2015-11-25 11:46:47

标签: javascript reactjs redux

我正在构建一个应用程序,我需要预先加载peopleplanet数据(它可能会在未来添加更多预加载要求< / em>)启动应用程序。我希望在商店中拥有代表应用程序全局状态为loaded: <boolean>的价值。只有当预加载要求people.loaded: trueplanet.loaded: true为真时,该值才为真。商店看起来像这样:

Store
├── loaded: <Boolean>
├── people:
│   ├── loaded: <Boolean>
│   └── items: []
├── planets:
│   ├── loaded: <Boolean>
│   └── items: []

单独的操作创建者会生成由PeoplePlanets reducer处理的所需异步请求和调度操作。如下所示(使用redux-thunk):

actions/index.js

import * as types from '../constants/action-types';
import {getPeople, getPlanets} from '../util/swapi';

export function loadPeople () {
  return (dispatch) => {
    return getPeople()
      .then((people) => dispatch(addPeople(people)));
  };
}

export function loadPlanets () {
  return (dispatch) => {
    return getPlanets()
      .then((planets) => dispatch(addPeople(planets)));
  };
}

export function addPeople (people) {
  return {type: types.ADD_PEOPLE, people};
}

export function addPlanets (planets) {
  return {type: types.ADD_PLANETS, planets};
}

export function initApp () {
  return (dispatch) => {
    loadPeople()(dispatch);
    loadPlanets()(dispatch);
  };
}

../util/swapi处理从LocalStorage或提出请求中提取人和行星数据。

initApp()动作创建者在呈现给DOM之前调用site.js中的其他动作创建者,如下所示:

site.js

import React from 'react';
import {render} from 'react-dom';
import Root from './containers/root';
import configureStore from './store/configure-store';
import {initApp} from './actions';

const store = configureStore();

// preload data
store.dispatch(initApp());

render(
  <Root store={store} />,
  document.querySelector('#root')
);

1。在Redux中管理应用程序的全局预加载状态的最佳实践是什么?

2。是否需要商店中的全局loaded州?

第3。在多个React组件中检查应用loaded状态的可扩展方法是什么?对于仅包含PeoplePlanet状态的容器似乎不合适需要知道全局应用状态,并且不处理PeoplePlanets的呈现。当在多个容器中需要全局loaded状态时,管理也会很痛苦。

Redux - multiple stores, why not?问题中引用Dan的部分回答。

  

使用reducer组合可以轻松实现&#34;依赖更新&#34; a la waitFor在Flux中通过手动编写一个减速器来调用其他减速器以及其他信息并按特定顺序。

4。 Dan是否通过调用其他reducers来调用嵌套的reducers?

2 个答案:

答案 0 :(得分:16)

首先,让我更正你的例子。

而不是

export function initApp () {
  return (dispatch) => {
    loadPeople()(dispatch);
    loadPlanets()(dispatch);
  };
}

你可以(而且应该)写

export function initApp () {
  return (dispatch) => {
    dispatch(loadPeople());
    dispatch(loadPlanets());
  };
}

您不需要传递dispatch作为参数 - thunk中间件负责处理此问题 当然,从技术上讲,您的代码是有效的,但我认为我的建议更容易阅读。

  
      
  1. 在Redux中管理应用程序的全局预加载状态的最佳实践是什么?
  2.   

你所做的似乎是正确的。没有具体的最佳实践。

  
      
  1. 商店中是否需要全局加载状态?
  2.   

没有。正如大卫在his answer中所说,你最好只存储必要的状态。

  
      
  1. 在多个React组件中检查应用加载状态的可扩展方法是什么?将容器和行星状态包含在仅需要知道全局应用程序状态且不处理人员或行星渲染的容器中似乎不合适。当在多个容器中需要全局加载状态时,管理也会很痛苦。
  2.   

如果您担心重复,请创建一个“选择器”功能并将其放在您的reducer旁边:

// Reducer is the default export
export default combineReducers({
  planets,
  people
});

// Selectors are named exports
export function isAllLoaded(state) {
  return state.people.loaded && state.planets.loaded;
}

现在您可以从组件中导入选择器,并在任何组件内的mapStateToProps函数中使用它们:

import { isAllLoaded } from '../reducers';

function mapStateToProps(state) {
  return {
    loaded: isAllLoaded(state),
    people: state.people.items,
    planets: state.planet.items
  };
}
  
      
  1. Dan是否通过调用其他reducers来调用嵌套的reducers?
  2.   

是的,减速器组合通常意味着调用嵌套的减速器 请参阅我关于此主题的免费Egghead教程视频:

答案 1 :(得分:6)

商店状态中的加载标志非常有意义。

但是你有太多了。您已获得state.people.loadedstate.planets.loaded以及state.loaded。后者来自前两个。你的商店真的不应该包含衍生国家。要么只有前两个要么只有后者。

我的建议是保留前两个,即state.people.loadedstate.planets.loaded。然后,您连接的组件可以导出最终加载状态。 e.g。

function mapStateToProps(state) {
    return {
        loaded: state.people.loaded && state.planets.loaded,
        people: state.people.items,
        planets: state.planet.items
    };
}