Redux - 管理预加载状态

IT技术 javascript reactjs redux
2021-05-18 12:12:11

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

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

单独的动作创建者发出所需的异步请求并分派由PeoplePlanets减速器处理的动作如下图(使用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()动作创建者在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')
);

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

2. 是否有loaded必要在 store中设置全局状态?

3.loaded在多个 React 组件中检查应用程序状态的可扩展方式是什么?为只需要知道全局应用程序状态而不处理or 的呈现的容器包含PeoplePlanet声明似乎是不正确的多个容器中需要全局状态时,管理起来也会很痛苦PeoplePlanetsloaded


引用Redux中 Dan 的部分回答- 多个商店,为什么不呢?问题。

使用reducer组合可以通过编写reducer手动调用其他reducer并以特定顺序调用其他reducer,从而在Flux中轻松实现“依赖更新”。

4、Dan 调用其他reducer 是否意味着调用嵌套reducer?

2个回答

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

代替

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

你可以(并且应该)写

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

你不需要dispatch作为参数传递——thunk 中间件会处理这个问题。
当然,从技术上讲,您的代码是有效的,但我认为我的建议读起来更容易。


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

你在做什么似乎是正确的。没有特定的最佳实践。

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

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

  1. 在多个 React 组件中检查应用程序加载状态的可扩展方式是什么?对于只需要知道全局应用程序状态而不处理 People 或 Planets 渲染的容器,包含 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;
}

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

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

function mapStateToProps(state) {
  return {
    loaded: isAllLoaded(state),
    people: state.people.items,
    planets: state.planet.items
  };
}
  1. Dan 调用其他减速器是否意味着调用嵌套减速器?

是的,reducer 组合通常意味着调用嵌套的 reducer。
请参考我关于这个主题的免费 Egghead 教程视频:

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

然而,你已经得到了太多。你有state.people.loadedstate.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
    };
}