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
(改变是 undefined
到 undefined
),这就是组件不重新渲染的原因。
所以决定将整个 state
公开为 options
,这正在改变组件的 this.props,所以它起作用了。
为了使其以更正确的方式工作,而不是将整个 state
暴露给组件,而只是 options
部分,reducer 的代码应该是:
return {
...state,
options: action.data
}
这样 state
就拥有 options
属性,mapStateToProps
看到它并且组件重新渲染。
我有非常简单的代码,我的想法是通过 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
(改变是 undefined
到 undefined
),这就是组件不重新渲染的原因。
所以决定将整个 state
公开为 options
,这正在改变组件的 this.props,所以它起作用了。
为了使其以更正确的方式工作,而不是将整个 state
暴露给组件,而只是 options
部分,reducer 的代码应该是:
return {
...state,
options: action.data
}
这样 state
就拥有 options
属性,mapStateToProps
看到它并且组件重新渲染。