【问题标题】:Redux - application state has the name of reducer as keyRedux - 应用程序状态以 reducer 的名称作为键
【发布时间】:2017-08-28 09:31:27
【问题描述】:

有人可以帮我解决这个问题吗? 我已经开始学习 React 和 Redux,但我在配置 redux 上卡住了几天。

我假设当某事触发一个动作时,redux 通过 reducers 函数堆栈应该返回一个代表我的应用程序状态的对象。 不幸的是,它返回一个带有 { reducerName => reducer result } 的对象基本上意味着如果我有 4 个 reducer,函数 store.getState() 会返回类似

{
 'reducerOne': entireApplicationState
 'reducerTwo': entireApplicationState
 'reducerThree': entireApplicationState
 'reducerFour': entireApplicationState
}

如果有人可以帮助我,我将非常感激,因为我已经完成了所有的想法:)

这是我的 application.js

import React from 'react';
import ReactDom from 'react-dom';
import HomePage from 'root_views/home';
import {store} from 'root_services/redux/store';

class Application extends React.Component {

        constructor(props) {
            super(props);
        }

        render() {
            return (
                <HomePage/>
            )
        }

}

var Provider = React.createClass({
        childContextTypes: {
            store: React.PropTypes.object.isRequired
        },
        getChildContext: function () {
            return {store: this.props.store}
        },
        render: function () {
            return this.props.children;
        }
});


ReactDom.render(
        <Provider store={store}>
            <Application/>
        </Provider>,
        document.getElementById('application')
);

我的 store.js

    import { createStore } from 'redux';

    import {rootReducer} from './reducers/container';

    export const store = createStore(
        rootReducer,
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );

我的 container.js 基本上包含了我所有的 reducer

import {combineReducers} from 'redux';

// This is just the action label
import {DATA_EXCHANGE_LOAD} from 'root_services/redux/actions/container'

const initialState = {
    data_exchange: {},
}

function dataExchange(state = {}, action) {

    switch (action.type) {

        case DATA_EXCHANGE_LOAD:
            return Object.assign({}, state, {
                data_exchange:{'reducerOne':'dataExchange'}
            });
            break;

        default:
            return initialState;
            break;

    }
};

function testReducer(state = {}, action) {
    switch (action.type) {

        case DATA_EXCHANGE_LOAD:
            return Object.assign({}, state, {
                data_exchange:{'reducerTwo':'testReducer'}
            });
            break;

        default:
            return initialState;
            break;
    }

};

// Export the combined reducers
export const rootReducer = combineReducers({
    dataExchange,
    testReducer
});

这是触发事件的动作:

export function dataExchangeLoad(){
    return {
        type: DATA_EXCHANGE_LOAD,
    }
};

这是触发操作的组件:

import React from 'react'
import "../components/layouts/header/header.less";
import {dataExchangeLoad} from "root_services/redux/actions/container"

export default class HomePage extends React.Component {

    constructor(props, {store}) {
        super(props);
        store.dispatch(dataExchangeLoad());
        console.log(store.getState());
    }

    render() {
        return (
            <div>
                <h1>test</h1>
            </div>
        )
    }
};

HomePage.contextTypes = {
    store: React.PropTypes.object,
}

这是结果:

Object {dataExchange: Object, testReducer: Object}

【问题讨论】:

  • 我可能是错的,但这正是 combineReducers() 函数所做的。按预期工作。
  • 对我来说看起来很奇怪,因为在我看过的所有教程中,它们只有一个“通用”对象,在存储状态中没有减速器名称 :( 无论如何,谢谢你的答案:)
  • 布莱格,教程。完美的自我破坏工具。请尝试使用 redux 文档:redux.js.org/docs/api/combineReducers.html .
  • 好的,现在我感觉自己像个傻瓜……非常感谢您抽出宝贵的时间! :)
  • 是的,另请参阅Structuring Reducers - Using combineReducers 文档页面,其中讨论了诸如此类的常见问题。

标签: javascript reactjs redux react-redux reducers


【解决方案1】:

正如 cmets combineReducers 已经回答的那样,确实可以这样工作。如果您想链接减速器,以便操作将依次通过所有减速器,您可以使用reduce-reducers。使用这个辅助函数可以做类似的事情(看起来这就是你想要实现的):

import reduceReducers from 'reduce-reducers';

const reducer1 = (state = {}, action) => { 
  if (action.type === 'foo') {
    return ({ 
      ...state, 
      touchedBy: ['reducer1'],
    })
  }
  return state;
};

const reducer2 = (state = {}, action) => { 
  if (action.type === 'foo') {
    return ({ 
      ...state, 
      touchedBy: state.touchedBy.concat('reducer2'),
    })
  }
  return state;
};

const reducer = reduceReducers(reducer1, reducer2);

expect(reducer({}, { type: 'foo' }))
    .toMatchObject({ touchedBy: ['reducer1', 'reducer2'] }); 

【讨论】:

    【解决方案2】:

    如果有人在看,上面在 cmets 中提供的链接已损坏。此链接有效并很好地解释了如何重命名来自减速器的状态。如果您不想阅读,请将您的减速器重命名为 import 或在您的 combineReducer 中重命名。

    示例 1:
    import billReducer as billState from "./reducers";

    示例2:
    const rootReducer = combineReducer({billState: billReducer});

    Using combineReducers

    【讨论】:

      猜你喜欢
      • 2019-07-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2019-07-28
      • 1970-01-01
      • 2017-03-28
      • 2018-08-04
      • 1970-01-01
      相关资源
      最近更新 更多