在react-redux中异步操作后更新状态

时间:2017-01-29 13:45:21

标签: javascript reactjs redux

一般的想法是有人点击按钮,操作从服务器获取数据并发送它。状态正在更新,页面上的内容正在发生变化。这个动作看起来很像:

     export function getPosts(page){
     return function(dispatch){
      axios.get(`${ROOT_URL}/home?page=${page}`)
          .then(response => {
            dispatch ({
            type: FETCH_POSTS,
            payload: response.data        
          })
          })
          .catch((error) => {
            console.log(error)
          });
    }
    }

Reducer非常简单:

      export default function(state={}, action){
      switch(action.type){
        case FETCH_POSTS:
        return {posts: action.payload, ...state};
      }
      return state;
    }

主页看起来就像那样:

    import React, { Component } from 'react';
    import * as actions from '../actions';
    import RequireAuth from './auth/require_auth';
    import { connect } from 'react-redux';
    import { compose } from 'redux';
    class Home extends Component {

    constructor(props) {
      super(props);
      this.state = {
        posts: 'loading....',
      };
      this.props.getPosts();
    }  
    handlePage(){
    console.log(this.props);
    let page = 3;
    this.props.getPosts();
    }

    componentWillReceiveProps(nextProps){
      let posts = nextProps.posts.posts.map((post) => {
      return (<li key={post._id}>{post.date}</li>)
      });
      this.setState({posts: posts});

    }
    shouldComponentUpdate(nextState, nextProps){
    console.log(nextProps.posts, nextState.posts);
    return true;
    }
      render(){
        return(
          <div>
            {this.state.posts}
            <button onClick={this.handlePage.bind(this)}>change something</button>
          </div>
          )
    }
    }

    function mapStateToProps(state){
      return {posts: state.post}
    }

    export default connect(mapStateToProps, actions)(Home);

我原以为状态会在componentWillReciveProps中更新但是没有发生。数据将在一段时间后被提取,因此我无法像这样设置状态。知道怎么做吗?

2 个答案:

答案 0 :(得分:3)

对于异步操作,有两种可能的方法:

  1. 额外的status旗帜
  2. 其他行动
  3. 工作流程如下:

    1. 获取数据,发送操作,将status设置为'fetching'
    2. 如果抓取成功,则发送一项操作,将status设置为'success'
    3. 如果fecthing失败,请发送一个操作,将status设置为'error'
    4. 进一步阅读:Redux :: Async actions

答案 1 :(得分:3)

编辑: redux-saga比redux-thunk更合适,因为它是用于完成所有副作用的容器。

您正在执行异步操作,因此您的调度员正在调度&#39;收到您的请求回复之前的操作,这就是您的商店没有更新的原因,也是您的状态。

要成功完成此操作,您必须提供一些超时以确保在分派操作之前收到响应。像这样:

 export function yourFunction(param) {
      return dispatch => {
        callApi(api_url, 'GET').then(res => {
           setTimeout(() => {
            dispatch(yourActionObject);
          }, 1000)
        }).catch(error => { console.log(error) })
      }
    }

但是超时(1000毫秒)可能有效,也可能无效。相反,您可以使用像redux-thunk这样的中间件。它会照顾你的超时延迟。

  

Redux Thunk中间件允许您编写返回函数而不是动作的动作创建者。 thunk可用于延迟动作的发送,或仅在满足特定条件时发送。

使用redux-thunk:

安装

npm install --save redux-thunk

然后,要启用Redux Thunk,请使用applyMiddleware():

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

然后你通常可以使用你的调度函数而不将它包装在setTimeout中。