React将状态键转换为promise

时间:2017-06-12 14:11:06

标签: javascript reactjs redux

我有一个使用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)));
    };
};

2 个答案:

答案 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