我有一个ReactJs应用程序,它使用Redux来管理它的商店。我的州是一个复杂的json,其文件可以改变。当我启动reducer时,我必须在从服务器获取内容之前指定其他的初始状态,我得到“未定义”#39;错误。以下是示例,
//Test.jsx
class Test extends React.Component{
componentWillMount(){
fetchContent({
type: SET_CONTENT
});
}
render(){
return(
<div> {this.props.header} </div>
)
}
mapStateToProps(state){
return{
header: state.reducer1.a.b.c
}
}
}
export default (mapStateToProps)(Test);
//reducer1.js
export default function reducer1(state = {}, action = {}) {
switch (action.type) {
case SET_CONTENT:
return Object.assign({}, action.data);
default:
return state;
}
}
//reducer2.js
export default function reducer2(state = {}, action = {}) {
switch (action.type) {
case SET_SOMETHING_ELSE:
return Object.assign({}, action.data);
default:
return state;
}
}
//CombinedReducer.js
export default combinedReducers(Object.assign({}, {reducer1}, {reducer2}))
&#13;
现在当组件第一次初始化时,state.reducer1.a.b.c
抛出未定义,因为此时似乎没有调用fetchContent()
。
所以我的问题是如何解决这个问题?在reducer中指定初始状态是唯一的选择吗?如下,
//reducer1.js
export default function reducer1(state = { a: { b: { c: "somedata"}}}, action = {}) {
switch (action.type) {
case SET_CONTENT:
return Object.assign({}, action.data);
default:
return state;
}
}
&#13;
答案 0 :(得分:0)
您可以这样做,但您也可以只更新mapState函数以检查是否存在第一个密钥。
function mapStateToProps(state){
return{
header: state.reducer1.a ? state.reducer1.a.b.c : <div>Loading..</div>
}
}
此外,我假设您的意思是在类定义之外使用mapStateToProps
,因为它是您传递给connect
而不是特定于该组件的函数:
class C {
...
}
function mapStateToProps (state) {}
connect(mapStateToProps)(C)
最后,您是否在fetchContent
来电中错过了发送?这是使用redux-thunk吗?
答案 1 :(得分:0)
在大多数情况下,您不应将所有响应数据存储在reducer中。您的州层次结构不应重复JSON响应的层次结构。
在reducer中只存储c
变量会更简单:
//reducer1.js
export default function reducer1(state = { c: undefined }, action) {
switch (action.type) {
case SET_CONTENT:
return Object.assign({}, state, { c: action.data.a.b.c });
default:
return state;
}
}
此外,您的代码中存在一些错误:
mapStateToProps
函数应该在类fetchContent
函数,而应将结果传递给dispatch。// Test.jsx
class Test extends React.Component{
componentWillMount(){
dispatch(fetchContent({
type: SET_CONTENT
}));
}
render() {
const { header } = this.props;
return header ? (
<div>{header}</div>
) : (
<div>Loading...</div>
);
}
}
function mapStateToProps(state) {
return {
header: state.reducer1.c
}
}
export default (mapStateToProps)(Test);