Javascript React将状态密钥转换为承诺

Javascript React将状态密钥转换为承诺,javascript,reactjs,redux,Javascript,Reactjs,Redux,我有一个使用redux架构的相对简单的React应用程序,出于某种原因,其中一个状态属性被更改为promise 我最终将尝试从数据库中提取数据用作数据,但我将从硬编码数据开始。我不明白为什么当Charts键到达布局/图表/索引组件时,它会变成一个承诺?据我所知,我的应用程序中没有包含任何api/异步功能。我已经包括了我认为与该问题相关的所有文件。我尝试过在不同的地方使用console.log记录状态,但我似乎无法确定状态决定何时或为什么更改为承诺。任何帮助都将不胜感激 项目的GitHub回购。

我有一个使用redux架构的相对简单的React应用程序,出于某种原因,其中一个状态属性被更改为promise

我最终将尝试从数据库中提取数据用作数据,但我将从硬编码数据开始。我不明白为什么当
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;