Dispatch(action) 改变了 store 状态但组件没有更新 [英] Dispatch(action) changes the store state but component is not updated

查看:49
本文介绍了Dispatch(action) 改变了 store 状态但组件没有更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有非常简单的代码,想法是通过 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 选项 = [];var setOptReducer = 函数(状态 = [],动作){console.log('setOptReducer 被调用状态', state, 'and action', action)开关(动作.类型){案例ADD_ITEM":返回 [...状态,动作数据]默认:返回状态;}};var setOptCreator = 函数(选项){console.log("setOptCreator 中的选项", options);返回 {类型:'ADD_ITEM',数据:选项}};var optDispatcher = 函数(选项){store.dispatch(setOptCreator(options));};const store = createStore(setOptReducer, options);函数 setOptions() {loadFromServer(optDispatcher);};函数 mapStateToProps(state) {console.log("mapStateToProps ",state);返回 {options: state.options};};var IndexContainer = React.createClass({渲染:函数(){返回 (<div>{console.log("使用选项渲染的索引", this.props.options)}

);}});函数 loadFromServer(回调){功能选项(值,标签){this.value = 值;this.label = 标签;}$.ajax({url: "/api/",数据类型:'json',缓存:假,成功:功能(数据){var 选项 = [];{..... 将一些元素从数据放入选项}console.log("loadFromServer 里面的选项是", options);回调(选项);console.log('回调后存储状态:', store.getState());}.绑定(这个)});};var Index = connect(mapStateToProps)(IndexContainer);ReactDOM.render(<提供者商店={商店}><路由器历史={createBrowserHistory()}><Route path="/" component={Index}/></路由器></提供者>,document.getElementById("容器"));

解决方案

基本上在你的 mapStateToProps 中,你有 options: state.options; 但现在没有东西 named 作为选项中的状态.来自文档 http://redux.js.org/docs/api/createStore.html,当你使用 createStore 传入 setOptReducer 作为参数时,它会创建一个只有一个 reducer 的 store,结果 stateown 是商店的价值.

您可以尝试将您的 mapStateToProps 更改为这个吗?

function mapStateToProps(state) {console.log("mapStateToProps ",state);返回{选项:状态};};

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

const store = createStore(options, []);

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

希望不要太混乱

I have pretty simple code, the idea is to fetch some data via ajax and make them available for the whole life of app. I need it this way because I use the Index component in many places, and I cannot afford fetch the data each time I render it. I see via all that messages in console, that the data I need is fetched and the store.state is updated and I see there all data I need, but Index component is never updated, and I don't get this data inside it. I am a novice, so probably I'm just blind to something stupid... I'd also appreciate any piece of advise regarding the whole architecture for my problem.

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

解决方案

Basically in your mapStateToProps, you have options: state.options; but right now there is no thing named as options in the state. From the docs http://redux.js.org/docs/api/createStore.html, when you use createStore passing in setOptReducer as argument, it creates a store with just one reducer and as a result state on it's own is the value of the store.

Could you try changing your mapStateToProps to this?

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

If this works, then you could rename some things, since right now it might be confusing. For example removing var options = [] and change the reducer function to options and have

const store = createStore(options, []);

It is recommended to use combineReducers to create a single root reducer out of many - and if you pass that to createStore, then the state is an object, and you can then do state.setOptReducer

Hope it's not too confusing

这篇关于Dispatch(action) 改变了 store 状态但组件没有更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆