2016-08-25 105 views
0

在迁移到反应redux土地后,我恋爱了..但是每当我尝试呈现路线并获得一个Can not读取mapStateToProps函数中未定义的属性'名称',该函数试图提取尚未加载的状态片段。Redux全局解决方案无法读取mapStateToProps中未定义的属性(如果商店尚未被水合)

例子:

state = { posts:{ blog : {byId:{},ids:[]}, wall: {byId:{},ids{} } }; 

说,一旦应用程序启动“index.js切入点”我从服务器获取的所有数据。基于所有数据都被加载的假设,我编码多个组件来过滤这些数据并对其进行处理。

当用户打开应用程序并导航到数据尚未加载的页面太快时会出现问题。然后我得到的“未定义无法读取属性‘名’”

例讨厌的错误:

//route ::/posts/blog/1 has something like this 
export default connect(
    (state,prop)=>({ 
    postId: state.posts.blog.byId[props.params.id].id 
    }))(props=><div>Post Id:{props.postId}</div>); 

如果之前博客商店填充它会给一个错误加载现在这个组件。

一个选项是返回一个占位符连接并首先检查后装入,或在初始化状态

initialState.blog = {byId:new Proxy({},{get:(obj,name)=>(name in obj)?obj[name]:{}}),ids[]} 
//this will suppress error by returing an empty object if undefined byId 

使用神奇的代理有什么办法,我可以要求组件通过加载其数据例如在它呈现之前调度一个动作?

我想要的东西就像propTypes所做的一样,只是它会推迟加载组件或其连接函数,直到商店确认它已完成加载。从propTypes

理念:

Component.propTypes = { 
    dispatch:PropTypes.func.isRequired, 
}; 

这会给一个错误,如果派遣不作为组件 道具供我想类似,但店面的东西。

例子:

Component.requireData = (state)=>({ 
    posts.blog:<placeHolder actionToDispatch="POST/BLOG/LOAD"/>, //if not posts.blog.isLoaded render placeholdercomponent insteed. 
}); 

所以它发生自动的,如果所需的数据尚未加载,该组件将不会呈现,并且会占位符代替呈现调度来加载所需的丢失数据的操作。

回答

4

每当组件的render被调用,这意味着父组件决定应该存在。 mapStateToProps可以自由地检查所需状态,并根据需要制作任何道具。如果国家的一部分缺失,它可以替代一些其他的道具。

系统的某些部分必须决定应何时呈现占位符而不是数据呈现组件。决定这一点的组件可能是组件本身或父组件。如果它是父级,那么你可以使这个组件可重用。

不管你用哪种方式打开它,你必须对决定所有数据是否准备好的部分进行编码。没有魔法。至少你需要传递一个字段名称,但是一个函数会更加灵活。此时您可以直接将此功能插入connect

因此,在我看来,仅仅编写一个简单的可重用父组件,它需要一个布尔属性来决定是否显示子对象或占位符,这不仅是一个很好且简单的解决方案,但在我看来,任何其他解决方案可能不会更好或更“神奇”。此外,“魔术”现在通常被认为是一个坏主意,因为它意味着缺乏透明度。通过坚持React-Redux的方式,你不会很难理解代码。

最后,不要指望React或Redux在你的应用程序不提供你的应用程序需要的数据时知道该怎么做。要么不要求它或提供它。创建一个简单的可重用父组件解决了这个问题,不需要数据(并决定要做什么,而不是React,Redux,或者第三方库都不知道决定)。

重述:创造你自己的魔法。它非常简单,快捷,并且完美地满足您的需求。

+0

我一直在为一个非常类似的问题而苦苦挣扎,“创造你自己的魔法”只是完全打开了我的理解。很好的回答,我觉得我现在更好地理解反应/还原/反应 - 还原生命周期 – Noah

相关问题