据我所知,如果父母组成部分重新渲染,那么除非他们实施Picker.js:11 Uncaught TypeError: _onChange is not a function
at onChange (Picker.js:11)
at HTMLUnknownElement.callCallback (react-dom.development.js:100)
at Object.invokeGuardedCallbackDev (react-dom.development.js:138)
at Object.invokeGuardedCallback (react-dom.development.js:187)
at Object.invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:201)
at executeDispatch (react-dom.development.js:466)
at executeDispatchesInOrder (react-dom.development.js:488)
at executeDispatchesAndRelease (react-dom.development.js:586)
at executeDispatchesAndReleaseTopLevel (react-dom.development.js:597)
at forEachAccumulated (react-dom.development.js:567)
at runEventsInBatch (react-dom.development.js:728)
at runExtractedEventsInBatch (react-dom.development.js:737)
at handleTopLevel (react-dom.development.js:4201)
at batchedUpdates (react-dom.development.js:12537)
at batchedUpdates (react-dom.development.js:1939)
at dispatchEvent (react-dom.development.js:4282
,否则其所有子女都会重新渲染。我made an example,这似乎不是真的。
我有3个组件:shouldComponentUpdate()
,<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/>
的功能组件,所以我不明白为什么它不会重新渲染。有人可以解释为什么会这样吗?我无法在与此用例相关的文档中找到任何内容。
答案 0 :(得分:11)
我会发布您的实际代码以供上下文使用:
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 Texts</div>;
}
在Application render中编写此代码时:
<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) },
);
在这两种情况下,这都是孩子:
function Child(props) {
return React.createElement("div", props, "Child Text");
}
这是什么意思?好吧,在您的StaticParent组件中,每次调用StaticParent的render方法时,您都会调用React.createElement(Child, null)
。在DynamicParent情况下,Child被创建一次并作为prop传递。由于React.createElement
是一个纯粹的函数,因此它可能会在某处因性能而被记忆。
在DynamicParent案例中,让孩子的渲染再次运行的是Child's道具的变化。例如,如果父母的状态被用作儿童的道具,则会在两种情况下触发重新渲染。
我真的希望丹·阿布拉莫夫没有出现在评论上,以摒弃这个答案,写作是一种痛苦(但很有趣)
答案 1 :(得分:4)
这主要是因为你有2个不同的孩子&#34;
<Child/>
强> 他们不是一回事,第一个是从prop
向下传递的Application -> DynamicParent
,而第二个是在Component
中呈现的StaticParent
,它们具有单独的渲染/生命周期。
您收录的示例
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>
);
}
}
答案 2 :(得分:1)
作为对SrThompsons的评论,答案是:“在DynamicParent案例中,使Child的渲染再次运行的原因是Child的道具发生了变化。例如,如果将父级的状态用作对Child的道具,则将触发-在两种情况下都呈现。”
因此,如果将道具传递给子组件,则该道具是否会传递给父组件(如果父组件重新渲染,那么它看起来会引起重新渲染(因此,对没有道具的孩子使用React.memo
))
“无论您是将组件实现为扩展React.Component的类组件还是功能组件,只要父容器再次渲染,都会再次调用render函数。”请阅读此处以获取更多信息,因为很棒的文章。 https://medium.com/free-code-camp/yeah-hooks-are-good-but-have-you-tried-faster-react-components-e698a8db468c”
答案 3 :(得分:-3)
它只会重新渲染已经发生变化的组件。如果子组件上没有任何内容发生更改,则不会重新呈现。