Redux - 等待承诺时加载指示器

onu*_*rhb 5 promise redux

我有一个简单的 redux 应用程序,它通过从 api 请求数据来显示文章。我想在等待承诺时显示“正在加载”指示器。我怎样才能实现这个?

ris*_*hat 4

涉及两方:存储和组件表示。

在商店中,每个减速器,您应该添加一个道具并将其命名为,例如loading。所以减速器的初始状态看起来像

// src/reducers/whatevs.js
const initialState = {
  // whatever
  loading: false
};
Run Code Online (Sandbox Code Playgroud)

然后,使用函数将此值传递到容器的 props 中connect,例如

export default connect(({whatevs}) => ({
  // props you want to use in this container, and
  loading: whatevs.loading
}));
Run Code Online (Sandbox Code Playgroud)

接下来,您想要调用一个操作并从中检索一个 Promise,所以它很简单

componentWillMount() {
  const promise = requestSomething();

  this.props.dispatch(() => {
    type: LOADING_SOMETHING
  });
  promise.then((smth) => this.props.dispatch(() => {
    type: LOADED_SOMETHING,
    ...smth
  }));
}
Run Code Online (Sandbox Code Playgroud)

因此,首先,您声称您请求了某些内容,因此您正在加载;然后,您声称已收到响应,因此您不再加载。相应的减速器看起来像

LOADING_SOMETHING: (state) => ({
  ...state,
  loading: true
})
Run Code Online (Sandbox Code Playgroud)

LOADED_SOMETHING: (state, {type, ...smth}) => ({
  ...state,
  ...smth,
  loading: false
})
Run Code Online (Sandbox Code Playgroud)

在组件中,只需依靠loadingprop 即可使其呈现加载指示器或实际数据:

render() {
  const {loading} = this.props;

  if (loading) {
    return (
      <LoadingIndicator />
    );
  } else {
    return (
      <WhateverComponent />
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

连接功能

React-redux 包中的函数connect包装了一个组件,并允许它从应用程序状态(即每个 Provider 组件更新时的 Store)接收 props。它是反应性地发生的,这意味着每次您调度一个操作时,都会从上到下。存储通常是一个普通对象(或者可能是 Immutable.js 的 Map 对象,或任何其他对象),按照惯例,它包含与减速器一样多的属性。

您可以使用 React DevTools 检查应用程序状态的值。只需打开它们,突出显示 Provider 组件,然后输入

$r.props.store.getState()
Run Code Online (Sandbox Code Playgroud)

您可以使用函数包装每个受控组件(可能称为容器或视图),connect使其接收状态的每次更新,并在组件依赖于应用程序状态的一部分发生变化时重新渲染。

例如,假设应用程序状态是

{
  authentication: {
    authenticated: null,
    username: null
  },
  photos: {
    items: [],
    favorites: []
  }
}
Run Code Online (Sandbox Code Playgroud)

你有一个组件

export default class Photos extends Component {
  render() {
    const {
      photoList
    } = this.props;

    return (
      <div>{this.renderPhotoList(photoList)}</div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

你真正想要的是photoList这个组件的 prop 引用photos.items应用程序状态的属性。然后将应用程序状态的photos.items属性连接到组件的photoListprop:

class Photos extends Component {
  render() {
    const {
      photoList
    } = this.props;

    return (
      <div>{doSomethingMeaningful(photoList)}</div>
    );
  }
}

export default connect((state) => ({
  photoList: state.photos.items // remember $r.props.store.getState()?
}))(Photos);
Run Code Online (Sandbox Code Playgroud)

或者,通过一些解构作业,

export default connect(({photos}) => ({
  photoList: photos.items
}))(Photos);
Run Code Online (Sandbox Code Playgroud)

connect函数接受一个或两个参数,在这个特定的示例中,只有一个参数将组件的 props 绑定到应用程序状态的属性。

可能有第二个参数,它是调度的函数:

import {
  fetchPhotos
} from 'actions/photos';

export default connect(({photos}) => ({
  photoList: photos.items
}), {
  fetchPhotos
})(Photos);
Run Code Online (Sandbox Code Playgroud)

这是一个不同的话题。

需要更深入地解释其connect工作原理吗?请参阅参考文献