2016-08-04 21 views
2

我有一个ReactJs应用程序,它使用Redux来管理其商店。我的状态是一个复杂的json,其文件可以改变。当我启动reducer时,我必须指定初始状态,否则在从服务器获取内容之前访问它时,会出现'undefined'错误。以下是例子,初始状态未定义在REDX连接的反应应用程序

//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}))

现在,当首次组件初始化,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; 
 
    } 
 
}

回答

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吗?

+0

所以唯一可能的解决方案如果任lnitialize状态像我一样还是从国家的数据访问每个级别做null检查! 是的,功能应该是在外面。因为我很快就写下了这个,所以没有仔细研究。是的,fetchContent是我内部调用dispatch的动作创建器上的一个函数。 – user3807940

+0

我不确定你的期望是什么,有些事情为你做空检查?你真的只有两个状态来检查a)predata和b)数据。这只是一个空检查,而不是'每个数据访问级别' – azium

0

在大多数情况下,您不应将所有响应数据存储在减速器中。您的状态层次结构不应该重复JSON响应的层次结构。

这会我更简单,只存储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函数,您应该将它传递给调度。
// 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); 
+0

这是否意味着redux-store只能存储一个简单的json?即使服务器的响应是复杂的,深度嵌套的json,我应该将它们转换成简单的1级json,然后再将它们存储到redux-store中? 此外,关于代码错误,这是一个打字错误:)我的意思是在类定义之外有mapStateToProps,而我的fetchContent是我的一个动作创建器中的一个函数,它在内部使用调度:) – user3807940

+0

@ user3807940,这取决于情况。如果您从服务器获得深度嵌套的json,请考虑使用'normalizr'包。它用于将深嵌套的json转换为1级数据。 – 1ven

+0

很酷,以前听说过normalizr,但从未尝试过。那就给它留言吧!感谢您的回复:) – user3807940

相关问题