React:当父组件重新渲染时,子组件是否总是重新渲染?
React: Do children always rerender when the parent component rerenders?
据我所知,如果一个父组件重新渲染,那么它的所有子组件都会重新渲染,除非它们实现 shouldComponentUpdate()
。我 made an example 这似乎不是真的。
我有 3 个组件:<DynamicParent/>
、<StaticParent/>
和 <Child/>
。 <Parent/>
组件负责呈现 <Child/>
但以不同的方式呈现。
<StaticParent/>
的渲染函数在运行前静态声明了 <Child/>
,像这样:
<StaticParent>
<Child />
</StaticParent>
虽然 <DynamicParent/>
在运行时动态处理接收和呈现 <Child/>
,如下所示:
<DynamicParent>
{ this.props.children }
</DynamicParent>
<DynamicParent/>
和 <StaticParent/>
都有 onClick
个侦听器来更改它们的状态并在单击时重新呈现。我注意到当单击 <StaticParent/>
时,它和 <Child/>
都会重新呈现。但是当我单击 <DynamicParent/>
时,只有父项而不是 <Child/>
被重新渲染。
<Child/>
是没有 shouldComponentUpdate()
的功能组件,所以我不明白为什么它不重新渲染。有人可以解释为什么会这样吗?我在文档中找不到与此用例相关的任何内容。
它只会重新渲染发生变化的组件。如果子组件没有任何变化,则不会重新渲染。
我会post你的实际上下文代码:
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
class DynamicParent extends React.Component {
state = { x: false };
render() {
console.log("DynamicParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
{this.props.children}
</div>
);
}
}
class StaticParent extends React.Component {
state = { x: false };
render() {
console.log("StaticParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
);
}
}
function Child(props) {
console.log("child");
return <div>Child Text</div>;
}
当您在应用程序渲染中编写此代码时:
<StaticParent />
渲染出来的是这样的:
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
而在现实中,发生的(大致)是这样的:
function StaticParent(props) {
return React.createElement(
"div",
{ onClick: () => this.setState({ x: !this.state.x }) },
React.createElement(Child, null)
);
}
React.createElement(StaticParent, null);
当您像这样渲染 DynamicParent 时:
<DynamicParent>
<Child />
</DynamicParent>
这就是实际发生的事情(再次粗略地说)
function DynamicParent(props) {
return React.createElement(
"div",
{
onClick: () => this.setState({ x: !this.state.x }),
children: props.children
}
);
}
React.createElement(
DynamicParent,
{ children: React.createElement(Child, null) },
);
在这两种情况下都是 Child:
function Child(props) {
return React.createElement("div", props, "Child Text");
}
这是什么意思?那么,在您的 StaticParent 组件中,每次调用 StaticParent 的 render 方法时,您都会调用 React.createElement(Child, null)
。在 DynamicParent 的情况下, Child 被创建一次并作为道具传递。并且由于 React.createElement
是一个纯函数,所以它可能会在某处被记住以提高性能。
Child 在 DynamicParent 情况下再次渲染 运行 的原因是 Child 的道具发生了变化。例如,如果 parent 的状态被用作 Child 的道具,那么在这两种情况下都会触发 re-render。
我真的希望 Dan Abramov 不会出现在评论中来破坏这个答案,写起来很痛苦(但很有趣)
这主要是因为你有两个不同的"children"。
- this.props.children
<Child/>
它们不是一回事,第一个是从 Application -> DynamicParent
传下来的 prop
,而第二个是 StaticParent
中呈现的 Component
,他们有单独的 rendering/life 周期。
您包含的示例
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
字面上等同于:
class Application extends React.Component {
render() {
// If you want <Child/> to re-render here
// you need to `setState` for this Application component.
const childEl = <Child />;
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
{childEl}
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
作为对 SrThompsons 回答的评论:"What would make Child's render run again in the DynamicParent case is a change in Child's props. If the parent's state was used as a prop to the Child, for example, that would trigger a re-render in both cases."
所以道具或不道具传递给 child 组件但是它可能看起来会导致重新渲染如果 parent 重新渲染(所以使用 React.memo
用于 child 没有道具 :))
"Whether you’re implementing your component as a class component that extends React.Component, or as a functional component, the render function is called again whenever the parent container renders again." 请阅读此处了解更多信息,因为这篇文章很棒。 https://medium.com/free-code-camp/yeah-hooks-are-good-but-have-you-tried-faster-react-components-e698a8db468c"
据我所知,如果一个父组件重新渲染,那么它的所有子组件都会重新渲染,除非它们实现 shouldComponentUpdate()
。我 made an example 这似乎不是真的。
我有 3 个组件:<DynamicParent/>
、<StaticParent/>
和 <Child/>
。 <Parent/>
组件负责呈现 <Child/>
但以不同的方式呈现。
<StaticParent/>
的渲染函数在运行前静态声明了 <Child/>
,像这样:
<StaticParent>
<Child />
</StaticParent>
虽然 <DynamicParent/>
在运行时动态处理接收和呈现 <Child/>
,如下所示:
<DynamicParent>
{ this.props.children }
</DynamicParent>
<DynamicParent/>
和 <StaticParent/>
都有 onClick
个侦听器来更改它们的状态并在单击时重新呈现。我注意到当单击 <StaticParent/>
时,它和 <Child/>
都会重新呈现。但是当我单击 <DynamicParent/>
时,只有父项而不是 <Child/>
被重新渲染。
<Child/>
是没有 shouldComponentUpdate()
的功能组件,所以我不明白为什么它不重新渲染。有人可以解释为什么会这样吗?我在文档中找不到与此用例相关的任何内容。
它只会重新渲染发生变化的组件。如果子组件没有任何变化,则不会重新渲染。
我会post你的实际上下文代码:
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
class DynamicParent extends React.Component {
state = { x: false };
render() {
console.log("DynamicParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
{this.props.children}
</div>
);
}
}
class StaticParent extends React.Component {
state = { x: false };
render() {
console.log("StaticParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
);
}
}
function Child(props) {
console.log("child");
return <div>Child Text</div>;
}
当您在应用程序渲染中编写此代码时:
<StaticParent />
渲染出来的是这样的:
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
而在现实中,发生的(大致)是这样的:
function StaticParent(props) {
return React.createElement(
"div",
{ onClick: () => this.setState({ x: !this.state.x }) },
React.createElement(Child, null)
);
}
React.createElement(StaticParent, null);
当您像这样渲染 DynamicParent 时:
<DynamicParent>
<Child />
</DynamicParent>
这就是实际发生的事情(再次粗略地说)
function DynamicParent(props) {
return React.createElement(
"div",
{
onClick: () => this.setState({ x: !this.state.x }),
children: props.children
}
);
}
React.createElement(
DynamicParent,
{ children: React.createElement(Child, null) },
);
在这两种情况下都是 Child:
function Child(props) {
return React.createElement("div", props, "Child Text");
}
这是什么意思?那么,在您的 StaticParent 组件中,每次调用 StaticParent 的 render 方法时,您都会调用 React.createElement(Child, null)
。在 DynamicParent 的情况下, Child 被创建一次并作为道具传递。并且由于 React.createElement
是一个纯函数,所以它可能会在某处被记住以提高性能。
Child 在 DynamicParent 情况下再次渲染 运行 的原因是 Child 的道具发生了变化。例如,如果 parent 的状态被用作 Child 的道具,那么在这两种情况下都会触发 re-render。
我真的希望 Dan Abramov 不会出现在评论中来破坏这个答案,写起来很痛苦(但很有趣)
这主要是因为你有两个不同的"children"。
- this.props.children
<Child/>
它们不是一回事,第一个是从 Application -> DynamicParent
传下来的 prop
,而第二个是 StaticParent
中呈现的 Component
,他们有单独的 rendering/life 周期。
您包含的示例
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
字面上等同于:
class Application extends React.Component {
render() {
// If you want <Child/> to re-render here
// you need to `setState` for this Application component.
const childEl = <Child />;
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
{childEl}
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
作为对 SrThompsons 回答的评论:"What would make Child's render run again in the DynamicParent case is a change in Child's props. If the parent's state was used as a prop to the Child, for example, that would trigger a re-render in both cases."
所以道具或不道具传递给 child 组件但是它可能看起来会导致重新渲染如果 parent 重新渲染(所以使用 React.memo
用于 child 没有道具 :))
"Whether you’re implementing your component as a class component that extends React.Component, or as a functional component, the render function is called again whenever the parent container renders again." 请阅读此处了解更多信息,因为这篇文章很棒。 https://medium.com/free-code-camp/yeah-hooks-are-good-but-have-you-tried-faster-react-components-e698a8db468c"