Dispatch(action) 更改商店状态但组件未更新

Dispatch(action) changes the store state but component is not updated

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

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")
);

基本上在您的 mapStateToProps 中,您有 options: state.options;,但现在状态中没有 named 作为选项。从文档 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 函数更改为选项并具有

const store = createStore(options, []);

建议使用 combineReducers 从多个根 reducer 中创建一个根 reducer - 如果将其传递给 createStore,则状态是一个对象,然后您可以执行 state.setOptReducer

希望不要太混乱

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

mapStateToProps 确实无法将 state.options 映射到 options,因为 state 不包含 options 属性,因为在 setOptReducer actionData 通过将它连接到 state 数组来保存,而不是通过将其作为对象 state:

的单独命名属性来保存
   case 'ADD_ITEM':
        return [
            ...state,
            action.data
        ]

所以 mapStateToProps 并没有真正改变 options(改变是 undefinedundefined),这就是组件不重新渲染的原因。 所以决定将整个 state 公开为 options,这正在改变组件的 this.props,所以它起作用了。 为了使其以更正确的方式工作,而不是将整个 state 暴露给组件,而只是 options 部分,reducer 的代码应该是:

    return {
        ...state,
        options: action.data
    }

这样 state 就拥有 options 属性,mapStateToProps 看到它并且组件重新渲染。