реагировать на редукцию асинхронным извлечением - PullRequest
0 голосов
/ 15 октября 2018

Я использую реагировать на редукцию, пытаюсь вызвать rest-api и вернуть данные.Выборка асинхронная, и мне нужно возвращать значение только после завершения выборки.

Я попробовал следующее, но это не сработало должным образом (в строке со звездочками «ожидание» отсутствует)) - Что мне делать?

Код:

-----

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;
};

Спасибо.

1 Ответ

0 голосов
/ 15 октября 2018

На самом базовом уровне вам нужно переместить асинхронную операцию из вашего редуктора.Вместо этого вы должны вызвать fetch() в вашем создателе действия и отправить действие после того, как fetch() завершит и разрешит ваш ответ JSON.Это будет выглядеть примерно так:В этом примере для асинхронного промежуточного программного обеспечения используется redux-thunk .Добавлено дополнительное действие для представления, когда начинается вызов fetch() и когда данные принимаются и анализируются.Это может использоваться, чтобы показать сообщение о загрузке или, возможно, отключить и / или условно отобразить определенные вещи.

Я создал рабочий пример .

Магазин:

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 к функциям внутреннего действия.Это используется для отправки действий / полезных нагрузок на редуктор.Редуктор должен просто получить готовые данные для обновления состояния.

Надеюсь, это поможет!

...