在redux连接反应app中初始状态未定义

时间:2016-08-04 15:09:43

标签: javascript reactjs redux reducers

我有一个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;
&#13;
&#13;

现在当组件第一次初始化时,state.reducer1.a.b.c抛出未定义,因为此时似乎没有调用fetchContent()

所以我的问题是如何解决这个问题?在reducer中指定初始状态是唯一的选择吗?如下,

&#13;
&#13;
//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;
&#13;
&#13;

2 个答案:

答案 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);
相关问题