在reducer之外用react-redux设置初始状态

时间:2017-03-20 17:58:36

标签: reactjs redux react-redux

我正试图将我的初始状态变成一个组件,但我似乎无法到达那里。我正在设置我的初始状态以获得名为topic_drpDwn的道具,但在MonitoringPage组件中,我看不到该状态出现。

我的index.js看起来像这样:

import 'babel-polyfill';
import React from 'react';
import { render } from 'react-dom';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import {Provider} from 'react-redux';
import './styles/styles.css'; //Webpack can import CSS files
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import configureStore from './store/configureStore';
import * as ReactBootstrap from 'react-bootstrap';

let initialState     = {
    topic_drpDwn: ["nifi", "drop 2", "tsys"]
};

const store = configureStore(initialState);


render (
    <Provider store={store}>
        <Router history={browserHistory} routes={routes} />
    </Provider>,
    document.getElementById('app')
);

我的MonitoringPage.js看起来像这样(这是我期待的this.props.topic_drpDwn

import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import * as monitoringActions from '../../actions/monitoringActions';
import * as ReactBootstrap from 'react-bootstrap';

class MonitoringPage extends React.Component {

    constructor (props, context) {
        super(props, context);

        this.state = {
            drplist: {drpTitle: "Sample topic selector", 
                      drpVal: ["tysys", "kafka-jmx", "nifi"]
                     }
        };

        this.onDropChange = this.onDropChange.bind(this);
    }

    onDropChange (event) {

        let drplist = Object.assign({}, this.state.drplist);

        console.log("drop changed")

        drplist.drpTitle = event;

        this.setState({drplist: drplist});
    }

    mkList (x) {

        return <ReactBootstrap.MenuItem eventKey={x}>{x}</ReactBootstrap.MenuItem>

    }

    render (title) {

        let data = [1,2,3,4]

        console.log("data", title)


        console.log("state: ", this.state)

        return (
            <div>
                <h1>Monitoring</h1>
                <h2>Monitoring Page under dev, example save button</h2>
                <input
                    type="text"

                     />
                <input
                    type="submit"
                    value="save" />
                <ReactBootstrap.DropdownButton title={this.state.drplist.drpTitle} id="bg-vertical-1" onSelect={this.onDropChange}>
                    {this.state.drplist.drpVal.map(this.mkList)}
                </ReactBootstrap.DropdownButton>
            </div>
        );
    }
}

function mapStateToProps(state, ownProps) {
    console.log("initial state indx: ", JSON.stringify(state));
    return {
        monitoring: state.monitoring,
        topic_drpDwn: state.topic_drpDwn
    };
}

export default connect(mapStateToProps) (MonitoringPage);

并配置商店如下所示:

export default function configureStore(initialState) {
    console.log("initial state: ", initialState)
    initialState = initialState || { topic_drpDwn: [] }
    console.log("initial state2: ", initialState)
    return finalCreateStore(
        rootReducer, 
        initialState
    );
}
这里的

console.log确实打印了index.js作为初始状态的内容,但如果我在this.props组件内部记录MonitoringPage,我就不会看到初始状态显示......

console.log("props:", this.props)
{
  "children": null, 
  "history": {}, 
  "location": {
    "$searchBase": {
      "search": "", 
      "searchBase": ""
    }, 
    "action": "POP", 
    "hash": "", 
    "key": "9cjw6a", 
    "pathname": "/monitoring", 
    "query": {}, 
    "search": "", 
    "state": null
  }, 
  "monitoring": [], 
  "params": {}, 
  "route": {
    "path": "monitoring"
  }, 
  "routeParams": {}, 
  "routes": [
    {
      "childRoutes": [
        {
          "path": "onboarding"
        }, 
        {
          "path": "topicregistry"
        }, 
        {
          "path": "monitoring"
        }, 
        {
          "path": "about"
        }
      ], 
      "indexRoute": {}, 
      "path": "/"
    }, 
    {
      "path": "monitoring"
    }
  ]
}

我正在尝试按照本指南关于如何在减速器之外设置初始状态。

https://egghead.io/lessons/javascript-redux-supplying-the-initial-state

----- EDIT --------

我在构造函数中取出了上下文,然后立即记录了道具并将其取回:

{
  "children": null, 
  "history": {}, 
  "location": {
    "$searchBase": {
      "search": "", 
      "searchBase": ""
    }, 
    "action": "POP", 
    "hash": "", 
    "key": "9cjw6a", 
    "pathname": "/monitoring", 
    "query": {}, 
    "search": "", 
    "state": null
  }, 
  "monitoring": [], 
  "params": {}, 
  "route": {
    "path": "monitoring"
  }, 
  "routeParams": {}, 
  "routes": [
    {
      "childRoutes": [
        {
          "path": "onboarding"
        }, 
        {
          "path": "topicregistry"
        }, 
        {
          "path": "monitoring"
        }, 
        {
          "path": "about"
        }
      ], 
      "indexRoute": {}, 
      "path": "/"
    }, 
    {
      "path": "monitoring"
    }
  ]
}

另外,我的monitoringReducer看起来像这样:

export default function monitoringReducer (state = [], action) {
    switch(action.type) {
        case 'TOPIC_SELECT':

            return Object.assign({}, state, topic_selected: [action.topic]);

        default:
            return state;
    }
}

我的rootReducer看起来像这样:

import {combineReducers} from 'redux';
import monitoring from './monitoringReducer';

const rootReducer = combineReducers({
    monitoring
});

export default rootReducer;

3 个答案:

答案 0 :(得分:2)

topic_drpDwn的缩减器是什么?现在只有一个监控减速器,因此所有州都处于状态监控状态。 state.topic_drpDwn没有reducer。所以redux说state.topic_drpDwn没有减速器。

答案 1 :(得分:0)

createStore(reducer, [preloadedState], [enhancer])

我们关注的是第二个参数preloadedState

从Redux引用createStore docs

  

[preloadedState](任意):初始状态。您可以选择将其指定为在通用应用程序中从服务器中保持状态,或者还原以前序列化的用户会话。如果您使用combineReducers生成reducer,则必须是明文   与传递给它的键相同的形状的对象。否则,你   可以自由地传递减速器可以理解的任何东西。

如果您正在使用combineReducers并且还将一个initialState(或preloadedState)传递给createStore,请确保密钥完全相同(不是更多,不是更少)。

如果违反此规定,您可能会在控制台中看到警告:

Unexpected key "topic_drpDwn" found in initialState argument passed to createStore. Expected to find one of the known reducer keys instead: "monitoring". Unexpected keys will be ignored.

<强>解决方案:

使用单个reducer管理所有内容并将其传递给createStore

finalCreateStore(reducer, initialState);

reducer管理外包。在您的情况下,状态键monitoringtopic_drpDwn都由同一个reducer处理。

但当然,这不是我们想要的任何App,因为我们需要有抽象的状态切片。因此,让我们分割并创建多个reducers来管理特定的状态切片。因此,您需要为topic_drpDwnmonitoring设置单独的缩减器。然后使用combineReducers创建rootReducer并将其传递给createStore

答案 2 :(得分:-1)

您应该使用react组件生命周期,并在componentWillMount()步骤调用操作中设置初始状态。

但更好的方法是 - 将reducer函数中的初始状态设置为默认参数:

const initialState = {
  someValue: {},
};

export default function someReducer(state = initialState, action) {
  switch (action.type) {
    case SOME_ACTION_TYPE:
      return { ...state, someValue: action.payload };
  }
}