【问题标题】:Dispatch(action) changes the store state but component is not updatedDispatch(action) 更改存储状态但组件未更新
【发布时间】:2015-11-21 04:25:12
【问题描述】:

我有非常简单的代码,想法是通过 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")
);

【问题讨论】:

    标签: javascript reactjs react-router redux


    【解决方案1】:

    基本上在您的 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 函数更改为 options 并具有

    const store = createStore(options, []);
    

    推荐使用combineReducers从多个reducer中创建一个单一的根reducer - 如果你将它传递给createStore,那么状态就是一个对象,然后你可以这样做state.setOptReducer

    希望不要太混乱

    【讨论】:

    • 你好,不,它没有做任何改变。如果有帮助,我在控制台中有: itemsReducer 被调用,状态 [] 和操作 Object {type: "@@redux/INIT"} mapStateToProps [] 使用选项呈现的索引未定义 mapStateToProps [] optionsReg 内部 loadFromServer 是 [option, option, option] optionsReg inside setOptCreator [option, option, option] itemsReducer 被调用状态 [] 和 action Object {type: "ADD_ITEM", data: Array[305]} mapStateToProps [Array[305]store state after callback: [Array[ 305]]
    • 我现在正在运行您的代码,如果您确实返回 {options: state};在 mapState 函数中,这将使索引更新,但我仍在检查为什么它之前不起作用
    • 多亏了你我解决了这个问题,现在我完全明白了。我把它作为一个单独的答案,因为我相信它可以帮助像我这样的新手))
    • 我肯定会花时间阅读整个Redux Docs。里面有很多非常棒的模式和想法可能有助于回答你的问题。丹写得很好,一步一步地写,所以很容易理解。希望对您有所帮助!
    【解决方案2】:

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

    mapStateToProps 真的无法将state.options 映射到options,因为state 不包含options 属性,因为在setOptReduceractionData 是通过将其连接到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 看到它并且组件重新渲染。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 2020-06-26
      相关资源
      最近更新 更多