Redux - 管理预加载状态

Ren*_*nis 16 javascript reactjs redux

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

Store
??? loaded: <Boolean>
??? people:
?   ??? loaded: <Boolean>
?   ??? items: []
??? planets:
?   ??? loaded: <Boolean>
?   ??? items: []
Run Code Online (Sandbox Code Playgroud)

单独的操作创建者会生成由Peopleand和Planetsreducers 处理的所需异步请求和调度操作.如下图所示(使用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);
  };
}
Run Code Online (Sandbox Code Playgroud)

../util/swapi 处理从LocalStorage或发出请求获取人员和行星数据.

initApp()动作创建者在site.js渲染到DOM之前调用其他动作创建者,如下所示:

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')
);
Run Code Online (Sandbox Code Playgroud)

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

2. loaded在商店中拥有全球国家是否必要?

3. loaded在多个React组件中检查应用程序状态的可扩展方法是什么?包含PeoplePlanet声明仅需要知道全局应用程序状态且不处理People或的呈现的容器似乎是不对的Planets.当loaded在多个容器中需要全局状态时,管理也是痛苦的.


引用Dan的部分答案来自Redux - 多家商店,为什么不呢?题.

使用reducer组合可以轻松地在Flux中实现"依赖更新"和"等待",方法是通过手动调用其他Reducer以及其他信息并按特定顺序调用reducer.

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

Dan*_*mov 17

首先,让我纠正你的例子.

代替

export function initApp () {
  return (dispatch) => {
    loadPeople()(dispatch);
    loadPlanets()(dispatch);
  };
}
Run Code Online (Sandbox Code Playgroud)

你可以(也应该)写

export function initApp () {
  return (dispatch) => {
    dispatch(loadPeople());
    dispatch(loadPlanets());
  };
}
Run Code Online (Sandbox Code Playgroud)

你不需要传递dispatch作为参数 - thunk中间件负责这一点.
当然,从技术上讲,您的代码是有效的,但我认为我的建议更容易阅读.


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

你在做什么似乎是正确的.没有具体的最佳实践.

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

不,正如大卫在回答中指出的那样,你最好只存储必要的状态.

  1. 在多个React组件中检查应用程序加载状态的可扩展方法是什么?将People和Planet状态包含在仅需要了解全局应用程序状态且不处理人物或行星渲染的容器中似乎是不对的.当在多个容器中需要全局加载状态时,管理也是痛苦的.

如果您担心重复,请创建一个"选择器"功能并将其与减速器放在一起:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


Dav*_*lsh 6

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

但是你有太多了.你有state.people.loaded,state.planets.loaded以及state.loaded.后者来自前两个.你的商店真的不应该包含派生状态.要么只有前两个要么只有后者.

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

function mapStateToProps(state) {
    return {
        loaded: state.people.loaded && state.planets.loaded,
        people: state.people.items,
        planets: state.planet.items
    };
}
Run Code Online (Sandbox Code Playgroud)