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