React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?
Posted
技术标签:
【中文标题】React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?【英文标题】:React Native & Redux: Why aren't child components re-rendering on every state update?React Native 和 Redux:为什么子组件不会在每次状态更新时重新渲染? 【发布时间】:2017-01-14 05:38:42 【问题描述】:在 React Native 和 Redux 中,我有一个 <NavigationCardStack/>
作为根组件。并且每次更新状态时,redux-logger 都会正确更新下一个/新状态。
并且在状态改变之后,当新更新的状态是控制台登录子组件时,它不会控制台记录更新的状态,而是控制台记录初始状态(在子组件中childPage.js
和日志记录:@987654324 @)。
可能是我错误地连接到 Redux 或遗漏了什么?因为,一切似乎都运行良好且有意义。
提前谢谢你!
这是我的代码的一些 sn-ps:
这是我的 reducer,即使添加和更新了其他属性,子组件也会在此处记录 initialState:
const initialState =
meetUp: false,
function itemReducer(state = initialState, action)
switch(action.type)
case ITEM_QUANTITY:
return
...state,
quantity: action.quantity
case ITEM_PRICE:
return
...state,
price: action.price
case ITEM_MEET_UP:
return
...state,
meetUp: action.meetUp
default:
return state
export default itemReducer
并像这样连接到根组件:
function mapStateToProps(state)
return
itemInfo: state.itemReducer,
...
export default connect(
mapStateToProps,
itemQuantity: (value) => itemQuantity(value),
itemPrice: (value) => itemPrice(value),
itemMeetUp: (value) => itemMeetUp(value),
)(NavigationRoot)
通过以下操作:
export function itemMeetUp(value)
return
type: ITEM_MEET_UP,
meetUp: value
export function itemQuantity(value)
return
type: ITEM_QUANTITY,
quantity: value
export function itemPrice(value)
return
type: ITEM_PRICE,
price: value
state=this.props 表示状态以及它应该如何传递给子组件
_renderScene (props)
const route = props.scene
return (
<route.component _handleNavigate=this._handleNavigate.bind(this) state=this.props/>
)
<NavigationCardStack
renderScene=this._renderScene
...
/>
【问题讨论】:
很难从所提供的 sn-ps 中看出 - 有没有机会建立一个 github repo 或 jsfiddle? 出于好奇,当您尝试从 childPage.js 组件中的 componentWillReceiveProps(props) 生命周期方法访问 console.log 时会发生什么?该方法是否被调用过?如果是这样,您能否记录 props 参数以确定组件是否接收到正确的属性? @bryonbean 我将控制台日志记录为constructor(props) super(props) console.log(props)
,它确实在页面第一次呈现时打印出所有初始属性。但是在更新之后,控制台日志不再被调用,因此尽管状态更新,它也永远不会被重新渲染,对吗?
不,构造函数只会在实例化时被调用一次,这是设置初始/原始属性的地方。组件属性的后续重新渲染可以通过添加一个名为componentWillReceiveProps(props)
的生命周期方法来确定。在此方法中,您可以调用console.log(props)
来确定在组件上设置了哪些新属性。 (见:facebook.github.io/react/docs/component-specs.html)
@bryonbean 我在render() console.log(props) return()
内部尝试过,当状态更新时,控制台会再次记录,但不是更新状态,而是控制台记录初始状态。我在render()return()
之前尝试过componentWillReceiveProps(props) console.log(props)
,但从未被调用,也没有控制台日志
【参考方案1】:
this issue 可能有关联吗?看起来很相似,NavigationCardStack
不会更新,即使 redux 状态发生变化,redux-logger
也会记录变化。我无法从您的代码示例中看出,但一种测试方法可能是 connect
孩子或一个孩子直接到您的 redux 商店,而不是让 NavigationCardStack
将商店状态作为道具传递?上面那个 github issue 也有一些 hacky 的解决方法,但是我对 react-native 不是很熟悉,所以在那里我帮不上什么忙。
【讨论】:
connect
不建议将所有孩子直接加入redux,这不是一个好习惯吗?
这并不是真正的坏习惯。如果您非常关心性能,那么您绝对应该自己检测和查看,但我最近看到的时尚做法是将组件树连接到尽可能低的位置,并且只映射您需要的道具。至少它使在层次结构中移动组件变得不那么乏味。
但这不是违背了 redux 的目的吗?您只想将其保持在一个流程中?
这并没有违背 redux 的目的。主要目的是您的所有状态都来自一个中心位置。让许多组件访问单个商店并不是一个坏习惯,如果您有多个不同的商店并且访问它们的方式不一致,就会出现毛茸茸的情况。这在principles section of the very excellent redux docs 中得到了更好的总结。 This other section 也与此对话相关,并且很有启发性。希望有帮助!【参考方案2】:
这基本上是在黑暗中刺探,完全基于我们在 cmets 中的对话,但是 _renderScene 方法是否绑定到构造函数中的组件?例如:
constructor (props)
super(props)
...
this._renderScene = this._renderScene.bind(this);
【讨论】:
不用担心,但是是的,我确实将方法绑定到构造函数中的组件。 @JoKo 没有看到更多你的代码是如何构造的,我很茫然,但我可以自信地告诉你,就你的子组件而言,this.props
的值永远不会改变;如果确实如此,componentWillReceiveProps
方法将触发,您将能够在那里记录它们。这意味着您的父组件也没有看到变化。希望我能提供更多帮助。
我也很茫然。我总是可以提供更多的代码。您可能需要哪一部分?
签到看看你是否看过我的最后一个例子。请告诉我。
对不起,我没有早点看到这个。我猜<NavigationCardStack ... />
的代码 sn-p 是根组件?很高兴看到它的全部以及你所有的 Redux 代码。还有一件事,这种风格/代码看起来很熟悉,是不是基于某处的教程?以上是关于React Native 和 Redux:为啥子组件不会在每次状态更新时重新渲染?的主要内容,如果未能解决你的问题,请参考以下文章
Wix React-Native-Navigation v2 和 redux-persist
React Native 已经有了异步存储。为啥我应该在我的 react native 应用中使用 Redux 和 Redux Thunk?