我有一个使用redux架构的相对简单的React应用程序,并且由于某种原因,其中一个状态属性被更改为promise。
我最终将尝试从数据库中提取数据以用作数据,但我开始使用硬编码数据。我无法弄清楚为什么在世界上Charts
键,当它到达布局/图表/索引组件时为什么它变成了Promise?我没有在我的应用程序中包含任何api / async功能。我已经包含了我认为与该问题相关的所有文件。我已经尝试过console.logging状态在各个地方,我似乎无法确定国家何时或为何决定改变承诺。任何帮助将不胜感激。
项目here的GitHub回购。
app.js
import 'babel-polyfill';
import React from 'react';
import { render } from 'react-dom';
import { browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import { AppContainer } from 'react-hot-loader';
import configureStore from './store/configureStore';
import Root from './containers/Root';
const initialState = {
Charts: {
PieChart: {
data: {
failed: false,
isfetching: false,
contains: null
},
msg: 'Preparing to fetch',
width: '100%',
height: '30vh',
options: {
title: 'Lateness of things',
backgroundColor: '#fff',
titlePosition: 'none',
pieHole: 0.7,
pieSliceTextStyle: {
color: 'black',
},
}
},
BarChart: {
chartType: 'BarChart',
width: '100%',
height: '30vh',
data: [
['Type', 'On time', 'Late', { role: 'annotation' }],
['Child', 4, 18, ''],
['Fire/EV/Body', 18, 21, ''],
['Truck', 49, 92, ''],
['Off-Highway/UTV', 18, 62, ''],
['Bus/Coach/WTORS', 5, 8, ''],
['Other', 11, 23, '']
],
options: {
isStacked: true,
height: 300,
legend: {position: 'top'},
hAxis: {minValue: 0}
}
}
}
};
const store = configureStore(initialState);
const history = syncHistoryWithStore(browserHistory, store);
render(
<AppContainer>
<Root store={store} history={history}/>
</AppContainer>,
document.getElementById('root'),
);
if(process.env.NODE_ENV !== 'production' && module.hot) {
module.hot.accept('./containers/Root', () => {
const NewRoot = require('./containers/Root').default;
render(
<AppContainer>
<NewRoot store={store} history={history}/>
</AppContainer>,
document.getElementById('root'),
);
});
}
reducer.js
import { routerReducer as routing } from 'react-router-redux';
import { combineReducers } from 'redux';
import * as types from '../actions/types';
const Charts = async (state = {}, action) => {
switch(action.type) {
case types.PIE_DATA_LOADING:
return {...state, PieChart: {isfetching: true, contains: null, failed: false}};
default:
return state;
}
};
const rootReducer = combineReducers({
Charts,
routing,
});
export default rootReducer;
容器/ Charts.js
import MainChart from './../components/layout/charts';
import {connect} from 'react-redux';
import { startPieDataLoad } from './../actions';
const mapStateToProps = (state) => {
return {
Charts: state.Charts,
};
};
const mapDispatchToProps = (dispatch) => {
return {
loadingPieChartData: () => {
return dispatch(startPieDataLoad());
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(MainChart);
组件/布局/图表/ index.js
import React from 'react';
import classNames from 'classnames';
import TotalChanges from './TotalChanges';
import ChangesByFunctionalGroups from './ChangesByFunctionalGroups';
import PropTypes from 'prop-types';
const MainChart = ({Charts}) => {
const BarChartData = Charts.BarChart;
const PieChartData = Charts.PieChart;
const PieChart = (!PieChartData.data.isfetching === false) ? (<TotalChanges chartData={PieChart} />) : (<div>{PieChartData.msg}</div>);
return (
<div className={classNames('mainWindow')}>
<div className={classNames('row')}>
<div className={classNames('col-sm-4')}>
{PieChart}
</div>
<div className={classNames('col-sm-4')}>
<ChangesByFunctionalGroups chartData={BarChartData} />
</div>
<div className={classNames('col-sm-4')}>
</div>
</div>
</div>
);
};
MainChart.propTypes = {
Charts: PropTypes.object,
loadingPieChartData: PropTypes.func
};
export default MainChart;
configureStore.js
import { createStore } from 'redux';
import rootReducer from '../reducers';
export default function configureStore(initialState) {
return createStore(
rootReducer,
initialState
);
};
action.js
import * as types from './types';
import fetch from 'isomorphic-fetch';
export function example(filter) {
return {
type: types.FILTER,
filter,
};
}
export function startPieDataLoad() {
return {
type: types.PIE_DATA_LOADING
};
};
export function finishPieDataLoad(data) {
return {
type: (data.err === true) ? types.PIE_DATA_LOADED_FAIL : types.PIE_DATA_LOADED_SUCCESS,
data: data.msg
};
};
export function fetchPieChartData() {
return (dispatch) => {
dispatch(startPieDataLoad);
return fetch('http://localhost:3001/cm/piechart').then(response => response.json()).then(json => dispatch(finishPieDataLoad(json)));
};
};
答案 0 :(得分:1)
首先要做的事情。在Redux中,你永远不会改变状态。在你的reducer中使用object.assign
case types.PIE_DATA_LOADING:
return {...state,
Object.assign({}, {PieChart: {isfetching: true, contains: null, failed: false}})
答案 1 :(得分:1)
问题是我将该操作声明为异步函数,导致它返回一个promise。我没有意识到那就是为什么我花了三个小时才找到它。
问题出在reducer.js
import { routerReducer as routing } from 'react-router-redux';
import { combineReducers } from 'redux';
import * as types from '../actions/types';
const Charts = (state = {}, action) => {
switch(action.type) {
case types.PIE_DATA_LOADING:
return {...state, PieChart: {isfetching: true, contains: null, failed: false}};
default:
return state;
}
};
const rootReducer = combineReducers({
Charts,
routing,
});
export default rootReducer;
请注意Charts =
后缺少 async