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

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

本文关键字:组件 更新 状态 action Dispatch 存储      更新时间:2023-09-26

我有非常简单的代码,想法是通过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;,但现在状态中没有命名为的选项。从文档http://redux.js.org/docs/api/createStore.html,当您使用传入setOptReducercreateStore作为参数时,它会创建一个只有一个reducer的存储,因此state本身就是存储的值。

你能试着把你的mapStateToProps改成这个吗?

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

如果这样做有效,那么你可以重命名一些东西,因为现在它可能会令人困惑。例如,删除var options = []并将减速器功能更改为选项并具有

const store = createStore(options, []);

建议使用combineReducers从多个根减少器中创建单个根减少器,如果将其传递给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.ops,因此它可以工作。为了使其以更正确的方式工作,而不将整个state暴露给组件,而只将options部分暴露出来,reducer的代码应该是:

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

通过这种方式,state变成具有options属性,mapStateToProps看到它并重新渲染组件。