У меня есть проект, который использует React + Redux + Thunk, и я новичок в стеке. У меня есть сценарий, в котором я извлекаю массив из вызова API в моем действии / редукторе, но это не повторный рендеринг в компоненте / контейнере, подключенном к Store. Компонент отображает первый раз, когда я запускаю приложение, но в этот момент массив равен undefined
при входе в консоль.
Я пытаюсь отобразить длину массива, поэтому всегда получается 0
. С ReduxDevTools я вижу, что состояние network_identities
заполняется правильно и больше нуля ... Где я ошибаюсь?
Вот мой пример действия
///////////// Sample action /////////////
import axios from 'axios';
const url = '[email protected]';
const authorization = 'sample_auth';
export function fetchConnections() {
const params = {
headers: {
authorization,
},
};
return (dispatch) => {
// call returns an array of items
axios.get(`${url}/connection`, params)
.then((connections) => {
let shake_profiles = [];
let connected_profiles = [];
let entity_res;
// map through items to fetch the items data, and split into seperate arrays depending on 'status'
connections.data.forEach((value) => {
switch (value.status) {
case 'APPROVED': case 'UNAPPROVED':
{
axios.get(`${url}/entity/${value.entity_id_other}`, params)
.then((entity_data) => {
entity_res = entity_data.data;
// add status
entity_res.status = value.status;
// append to connected_profiles
connected_profiles.push(entity_res);
});
break;
}
case 'CONNECTED':
{
axios.get(`${url}/entity/${value.entity_id_other}`, params)
.then((entity_data) => {
entity_res = entity_data.data;
entity_res.status = value.status;
shake_profiles.push(entity_res);
})
.catch(err => console.log('err fetching entity info: ', err));
break;
}
// if neither case do nothing
default: break;
}
});
dispatch({
type: 'FETCH_CONNECTIONS',
payload: { shake_profiles, connected_profiles },
});
});
};
}
Редуктор образцов
///////////// Sample reducer /////////////
const initialState = {
fetched: false,
error: null,
connections: [],
sortType: 'first_name',
filterType: 'ALL',
shake_identities: [],
network_identities: [],
};
const connectionsReducer = (state = initialState, action) => {
switch (action.type) {
case 'FETCH_CONNECTIONS':
console.log('[connections REDUCER] shake_profiles: ', action.payload.shake_profiles);
console.log('[connections REDUCER] connected_profiles: ', action.payload.connected_profiles);
return { ...state,
fetched: true,
shake_identities: action.payload.shake_profiles,
network_identities: action.payload.connected_profiles,
};
default:
return state;
}
};
export default connectionsReducer;
Образец магазина
///////////// Sample Store /////////////
import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';
import reducers from './reducers';
const middleware = applyMiddleware(promise(), thunk);
// Redux Dev Tools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducers, composeEnhancers(middleware));
export default store;
Пример компонента - посмотрите, завершил ли API выборку массива, а затем отобразите длину массива
///////////// Sample Component /////////////
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import CSSModules from 'react-css-modules';
import * as ConnectionActions from 'actions/connections';
import styles from './styles.scss';
function mapStateToProps(state) {
return {
network_identities: state.connections.network_identities,
loadedConnections: state.connections.fetched,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Object.assign({}, ConnectionActions), dispatch),
};
}
class Counter extends Component {
componentWillMount() {
const { network_identities, actions } = this.props;
if (!network_identities.length) {
console.log('||| fetching Connections');
actions.fetchConnections();
}
}
render() {
let { network_identities, loadedConnections} = this.props;
console.log('[Counter] network_identities[0]: ', network_identities[0]);
console.log('[Counter] network_identities: ', network_identities);
console.log('[Counter] loadingConnections: ', loadingConnections);
return (
<div>
<Link to="/network">
<div>
<span>Connections</span>
{ !loadedConnections ? (
<span><i className="fa fa-refresh fa-spin" /></span>
) : (
<span>{network_identities.length}</span>
) }
</div>
</Link>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CSSModules(Counter, styles));
Я подозреваю, что я либо изменяю состояние в своем редукторе, либо неправильно использую Thunk.
connections.data.forEach
отрывочно, так как он не будет ждать завершения выборки. После этого извлечения изменят состояние, но не вызовут повторную визуализацию, потому что диспетчеризация уже запущена. Может быть лучше сопоставитьconnections
с обещаниями и дождаться результатов с.all()
. - person Oblosys   schedule 11.04.2018[connections REDUCER]
журналах консоли вconnectionsReducer
печатаются два пустых массива? - person Oblosys   schedule 11.04.2018[connections REDUCER]
изначально регистрирует[]
. Когда я проверяю его и значение оценивается, он становится правильным массивом, заполненным данными ... Также я пробую ваш подход Promise.all (), просто пытаясь выяснить, как его реализовать в данный момент :) - person AdB   schedule 11.04.2018