用异步获取来响应redux [英] react redux with asynchronous fetch

查看:58
本文介绍了用异步获取来响应redux的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用react redux,并尝试调用rest-api,并返回数据.提取是异步的,仅在提取完成后才需要返回值.

I am using react redux, and trying to call rest-api, and return the data. The fetch is asynchronous, and I need to return value only when the fetch is finished.

我尝试了以下操作,但这种方法无法正常运行(在带有星号的行上没有等待")-我该怎么办?

I tried the following, but this didn't work properly (there is no 'wait' on the line that is with asterisks) - What shall I do?

代码:

-----

var _getData = function()  
{
return new Promise((resolve, reject) => {
    let options = {
        method: 'GET',
    }
    let _url = "my web return json";
    fetch(_url, options)
    .then(response => 
        response.json().
            then(data => resolve({
                data: data,
                status: response.status
            }))
            .catch(err => reject(
                {error_data: err}
                )
            )

    )
    .catch(
        err =>
        {
            console.log(err);
            reject(err);
        }
    )
    })
}

// ...
const reducer = (state = initialState, action) => {
if (action.type === 'GET_DATA_FIRST') {
    let x = {}
    setTimeout(function () {
        _getData().then(
            (res) =>
            {
                x = res;
            }
        ) }, 0)
    // ******** NEED TO WAIT UTIL _getData ends and return a value ***** 


    return {
        ...state,
        myData: x
    }
}
return state;
};

谢谢.

推荐答案

在非常基本的级别上,您需要将异步操作从您的reducer中移出.相反,您应该在动作创建者中触发 fetch(),并在 fetch()完成并解决JSON响应后调度动作.它看起来像以下内容.此示例将 redux-thunk 用于异步中间件.添加了一个附加操作,以表示 fetch()调用何时开始以及何时接收和解析数据.这可以用于显示加载消息,或者可以禁用和/或有条件地渲染特定内容.

At a very basic level you need the move the asynchrounous operation out of your reducer. Instead you should trigger the fetch() in your action creator and dispatch an action once the fetch() has completed and resolved your JSON response. It would look something like the following. This example uses redux- thunk for async middleware. An additional action has been added to represent when the fetch() call starts and when the data is received and parsed. This can be used to show a loading message or perhaps disable and/or conditionally render specific things.

我创建了一个有效的示例.

商店:

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

const middleware = [ thunk ];

const store = createStore(
  rootReducer,
  applyMiddleware(...middleware)
);

export default store;

减速器:

import { combineReducers } from 'redux';
import { GET_DATA_FIRST, REQUEST_DATA } from '../actions';

const initialState = {
  isFetching: false,
  myData: []
};

const things = (state = initialState, action) => {
  switch (action.type) {
    case REQUEST_DATA:
      return {
        ...state,
        isFetching: true
      };
    case GET_DATA_FIRST:
      return {
        ...state,
        isFetching: false,
        myData: action.myData
      };
    default:
      return state;
  }
};

const rootReducer = combineReducers({
  things // this key can be called anything, 'things' is just an example
});

export default rootReducer;

动作:

export const REQUEST_DATA = 'REQUEST_DATA'; // action to represent waiting for response
export const GET_DATA_FIRST = 'GET_DATA_FIRST'; // action to represent receiving of data

export const requestData = () => ({ type: REQUEST_DATA });

export const getDataFirst = myData => ({ type: GET_DATA_FIRST, myData });

export const fetchData = () => dispatch => {
  dispatch(requestData());
  return getData().then(things => {
    // simulated delay
    setTimeout(() => {
      return dispatch(getDataFirst(things))
    }, 1000);
  });
};

const getData = () => {  
  return fetch('https://jsonplaceholder.typicode.com/todos').then(res => res.json());
}

组件:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchData } from './actions';

class ThingsList extends Component {
  constructor(props) {
    super(props);    
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.dispatch(fetchData());
  }

  render() {
    return (
      <div>
        <button type="button" onClick={this.handleClick}>GET DATA</button>
        {this.props.isFetching && <div>Loading...</div>}
        <ul>
          {this.props.myData.map(d => <li key={d.id}>{d.title}</li>)}
        </ul>        
      </div>
    );
  }
}

const mapStateToProps = ({ things: { myData, isFetching } }) => ({
  myData,
  isFetching
});

export default connect(mapStateToProps)(ThingsList);

注意诸如 fetchData()之类的动作如何将 dispatch 传递给内部动作函数.这用于将操作/有效负载分派给减速器.减速器应该只获取准备使用的数据来更新状态.

Notice how the actions such as fetchData() pass dispatch to inner action functions. This is used to dispatch actions/payloads to the reducer. The reducer should just get ready-to-use data to update state with.

希望有帮助!

这篇关于用异步获取来响应redux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆