在React中,当属性发生变化后重新渲染组件。

10
在React文档中,它说:
默认情况下,当组件的状态或props更改时,组件将重新渲染。
我理解状态变化会引起重新渲染,但是对于props变化,我不太确定。据我所知,props总是从父组件传递到子组件。当父组件重新渲染(例如由于状态改变),所有子组件也会重新渲染(忽略shouldComponentUpdate)。因此,如果父组件重新渲染,则所有子组件都将重新渲染,无论我是否向它们传递了新的props。如果我确实向子组件传递了新的props,那么子组件重新渲染的原因仅仅是因为父组件正在重新渲染,而不是因为我传递了新的props。
是否存在这样的场景:父组件向子组件传递新的props导致子组件重新渲染,但这不仅仅是因为父组件重新渲染导致的?
是否可能看到一个例子,其中一个组件将重新渲染,因为它收到了新的props,而不是因为父组件重新渲染(或者它自己的状态发生了变化)?
对不起,如果这是一个基础问题,我是React的新手。
编辑:我看到Redux可以通过传递新的props来导致组件重新渲染,我想知道Redux在背后做了什么来实现这一点。

2
这是一个很棒的问题。 - Yatrix
4个回答

5

回答您在最后提出的问题:

  • 如果子组件是一个 PureComponent 或者被包裹在 React.memo 中,只有在其接受到的props改变时才会重新渲染。如果父组件重新渲染,那么子组件会比较它接收到的props,如果它们和之前传递的props相同,则不会重新渲染。

  • 如果子组件不是 PureComponent 或者未被包裹在 React.memo 中,则任何时候父组件重新渲染,它都会重新渲染。


这很有道理,但我很好奇除了状态改变或父组件重新渲染之外,是什么导致组件首次重新渲染的。我已经更新了原始问题以使其更清晰。 - ech
如果任何与你的组件连接的React context发生更改。或者从组件中调用this.forceUpdate()如果你正在使用Redux: 你可以将connectmapStateToProps想象成创建一个组件,该组件从Redux抓取一些state并将其作为props传递给其子组件。在那个上下文中,子代是您将传递给React-Redux的connect函数的组件。 - Slbox
我可能错了,但看起来 Redux 创建了一个包装组件,并且如果更新的 Redux 状态会导致子组件的 props 发生变化,则强制渲染此包装组件,从而导致子组件也重新渲染,现在具有新的 props。这不同于组件重新呈现,因为其 props 已更改,如果您明白我的意思的话。对于混淆,我只是想清楚地说明在哪里更改 props 会导致组件重新呈现的示例。 此外,我认为上下文更改与 props 更改是不同的。 - ech
Redux的state映射props。因此,你从mapStateToProps返回的Redux state 成为组件的props。我不是很清楚你试图概述的区别是什么。上下文变化与props变化是不同的,但对于本讨论的目的来说没有实质性的意义,除非你实现了shouldComponentUpdate - Slbox

1
我对React并不陌生,也曾问过同样的问题。有一篇文章为我澄清了这个问题:https://thoughtbot.com/blog/react-rendering-misconception 重新渲染是为了检查是否需要更新DOM。如果你已经实现了shouldComponentUpdate或者使用memo进行了包装(都返回false),那么重新渲染会被跳过。
如果一个子组件使用redux或context进行连接,即使没有父组件重新渲染,它也可能会重新渲染。

这篇文章很好,也许我的困惑在于实际语句“默认情况下,当组件的状态或属性改变时,组件将重新渲染”,而语句中提到的属性更改部分是否意味着该组件被memo包装? - ech
从这个角度来看:组件的Props可能是父级状态,这就是为什么它会类似于它的原因。如果组件实现了shouldComponentUpdate或被包装在memo中,则不会重新渲染,无论父级是否更改(它仅在该方法中给定的条件下重新渲染)。是的,如果props/state没有更改但父级重新渲染,则整个树将重新渲染(用于差异检查,可能不是真正的DOM更改)。这通常非常快,但一旦渲染变得昂贵,shouldComponentUpdate可以帮助您防止它。 - Dennis

0

当您使用provider、HOC或Redux与mapStateToProps等时,props会从其他组件注入props而发生更改。


一个使用mapStateToProps的HOC或组件仍然会重新渲染(调用它的render方法),不是吗? - Yatrix
是的,你可以通过shouldComponentUpdate避免组件重新渲染,并在特定的props更改时进行渲染。但要注意对象和数组,因为引用会发生变化,所以必须深度比较值。 - JB_DELR

0
  1. Redux 的 Connect 中间件类似于订阅,每个子组件都可以通过订阅直接连接到 store,当 store 发生变化时,store 会尝试重新同步所有已连接的组件。任何组件接收到的新数据都会作为 props,导致重新渲染。
  2. 任何从其状态之外进行更改的组件只能通过 props 进行,因此它类似于父组件传递新数据 / redux store 推送新数据到组件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接