Javascript React将状态密钥转换为承诺
我有一个使用redux架构的相对简单的React应用程序,出于某种原因,其中一个状态属性被更改为promise 我最终将尝试从数据库中提取数据用作数据,但我将从硬编码数据开始。我不明白为什么当Javascript React将状态密钥转换为承诺,javascript,reactjs,redux,Javascript,Reactjs,Redux,我有一个使用redux架构的相对简单的React应用程序,出于某种原因,其中一个状态属性被更改为promise 我最终将尝试从数据库中提取数据用作数据,但我将从硬编码数据开始。我不明白为什么当Charts键到达布局/图表/索引组件时,它会变成一个承诺?据我所知,我的应用程序中没有包含任何api/异步功能。我已经包括了我认为与该问题相关的所有文件。我尝试过在不同的地方使用console.log记录状态,但我似乎无法确定状态决定何时或为什么更改为承诺。任何帮助都将不胜感激 项目的GitHub回购。
Charts
键到达布局/图表/索引组件时,它会变成一个承诺?据我所知,我的应用程序中没有包含任何api/异步功能。我已经包括了我认为与该问题相关的所有文件。我尝试过在不同的地方使用console.log记录状态,但我似乎无法确定状态决定何时或为什么更改为承诺。任何帮助都将不胜感激
项目的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'),
);
});
}
container/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);
组件/布局/图表/索引.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;
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)));
};
};
第一件事。在Redux中,您永远不会改变状态。在减速器中使用object.assign
case types.PIE_DATA_LOADING:
return {...state,
Object.assign({}, {PieChart: {isfetching: true, contains: null, failed: false}})
问题是我将操作声明为异步函数,这导致它返回一个承诺。我没有意识到它就在那里,所以我花了三个小时才找到它 问题在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;
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;
注意图表后缺少异步=是否
dispatch
返回承诺?你能发布你的商店配置吗(fiddle/repo会很好)?我认为这是一个中间件问题@根据我的理解,CooperCampbellit不应该这样做,除非您正在实现thunk中间件或其他东西。不管怎样,我的应用程序甚至没有时间启动返回承诺的函数,组件第一次收到承诺时,它就是一个承诺。另外,我不认为返回承诺会扰乱该州的关键图表,是吗@DanielB@John我添加了配置文件,很简单,我现在甚至没有使用中间件,因为这也是我的第一个爱好。谢谢你的帮助,我目前还没有回购协议。我可以在github上获得它,但是如果你直接给我发消息,我可以给你发送一份完整应用的副本。很抱歉给您带来不便。您能给我们看一下您的startPieDataLoad()
action创建者吗?我在这里看不到。我会查看回购协议,并对其进行调试。然后我会发布我建议的所有更改。谢谢,我还认为扩展语法否定了使用Object.assign()的需要?不管怎样,我都会做出改变的。我发现了错误。是减速器有讨厌的异步,我没有意识到我的朋友添加了异步。这导致函数返回一个承诺来代替新状态。谢谢你的帮助,也谢谢你的关注,我希望我没有浪费你太多的时间。如果您想发布一个建议删除async关键字的答案,我将选择它作为right@CooperCampbell. 哈哈,没关系。我还没有机会看一看。你应该张贴你自己的答案。如果遇到任何问题,请向我发送PM,或者我的联系信息在这里。如果您正确使用了扩展运算符,则不一定需要Object.assign()
。但是@CooperCampbell,我认为在还原程序中使用spread运算符返回state.Chart.PieChart
对象时可能会遇到语法问题。不要忘记将此标记为答案。很好的工作伙伴。它不会让我再过两天,再次感谢你帮我做这件事。我盯着它发疯了,想知道为什么它会决定随机回复承诺。你确定你不想要信用卡吗@JohnPost在您将此标记为正确答案之前,先在此处发布解决问题的代码,以便将来可能找到此帖子的任何人都能从中受益。
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;