Dispatch(action)更改存储状态,但组件未更新

时间:2015-11-21 04:25:13

标签: javascript reactjs react-router redux

我有非常简单的代码,我的想法是通过ajax获取一些数据并使它们在应用程序的整个生命周期中都可用。我需要这种方式,因为我在许多地方使用Index组件,而且每次渲染时都无法获取数据。 我通过控制台中的所有消息看到,我需要获取所需的数据并更新store.state,我看到我需要的所有数据,但索引组件永远不会更新,我不会在里面获取这些数据它。 我是新手,所以我可能只是对愚蠢的事情视而不见...... 我也很欣赏有关我的问题的整个架构的任何建议。

var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var Route = require('react-router').Route;
var createBrowserHistory = require('history/lib/createBrowserHistory');
var createStore = require('redux').createStore;
var Provider = require('react-redux').Provider;
var connect = require('react-redux').connect;

window.onload=setOptions;

var options = [];
var setOptReducer = function (state = [], action) {
    console.log('setOptReducer was called with state', state, 'and action', action)
    switch (action.type) {
        case 'ADD_ITEM':
            return [
                ...state,
                action.data
            ]
        default:
            return state;
    }
};

var setOptCreator = function (options) {
    console.log("options inside setOptCreator ", options);
    return {
        type: 'ADD_ITEM',
        data: options
    }
};

var optDispatcher = function(options) {
    store.dispatch(setOptCreator(options));
};

const store = createStore(setOptReducer, options);

function setOptions() {
    loadFromServer(optDispatcher);
};

function mapStateToProps(state) {
    console.log("mapStateToProps ",state);
    return {options: state.options};
};

var IndexContainer = React.createClass({
    render: function () {
        return (
            <div>
                {console.log("Index rendered with options ", this.props.options)}
            </div>
        );
    }
});

function loadFromServer(callback) {
    function option(value, label) {
        this.value = value;
        this.label = label;
    }
    $.ajax({
        url: "/api/",
        dataType: 'json',
        cache: false,
        success: function (data) {
            var options = [];
            {.....put some elements from data to options}
            console.log("options inside loadFromServer is ", options);
            callback(options);
            console.log('store state after callback:', store.getState());
        }.bind(this)
    });
};

var Index = connect(mapStateToProps)(IndexContainer);

ReactDOM.render(
    <Provider store={store}>
            <Router history={createBrowserHistory()}>
                <Route path="/" component={Index}/>
            </Router>
    </Provider>,
    document.getElementById("container")
);

2 个答案:

答案 0 :(得分:4)

基本上在mapStateToProps中,你有options: state.options;但是现在没有名为的东西作为状态中的选项。在文档http://redux.js.org/docs/api/createStore.html中,当您使用createStore作为参数传递setOptReducer时,它会创建一个只包含一个reducer的商店,因此state就可以了拥有是商店的价值。

您可以尝试将mapStateToProps更改为此内容吗?

function mapStateToProps(state) {
    console.log("mapStateToProps ",state);
    return {options: state};
};

如果这样可行,那么你可以重命名一些东西,因为现在它可能会令人困惑。例如,删除var options = []并将reducer函数更改为options并具有

const store = createStore(options, []);

建议使用combineReducers从多个中创建单个根reducer - 如果将其传递给createStore,则状态为对象,然后您可以执行{{1 }}

希望它不会太混乱

答案 1 :(得分:3)

最后在luanped的巨大帮助下,我找到了问题的根源,我相信值得作为一个单独的答案。

mapStateToProps实际上无法将state.options映射到options,因为state不包含options属性,因为在setOptReducer中通过将actionData数组连接到state数组来保存state,而不是将其作为对象 case 'ADD_ITEM': return [ ...state, action.data ] 的单独命名属性:

mapStateToProps

所以options并没有真正改变undefined(将undefined更改为state)以及该组件没有改变的原因重新渲染。 因此,决定将整个options公开为state,这正在改变组件的this.props,因此它可以工作。 为了使其工作更正确,不将整个options暴露给组件,而只暴露 return { ...state, options: action.data } 部分,reducer的代码应该是:

state

这种方式options变为mapStateToProps属性,// article.php public function my_complex_query() { // code here. Eloquent, or Query Builder or // Raw SQL return $result; } 看到它并且组件重新渲染。