[英]Functional component definition inside class component's render() method, state resets when created through JSX, but not when called directly
如果我在类组件的render()
方法中定义了一个功能组件,那么每次调用类组件的render()
方法时都会重置组件的状态。 如果我直接调用功能组件,状态不会重置。
看下面的例子:
import React from 'react';
import Counter from './Counter'
const MilliCounter = ({name}) => {
return <Counter name={name} initial={1e6} />
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
flag: false
}
}
onButtonClick = (event) => {
this.setState({flag: !this.state.flag});
};
render() {
const HundoCounter = ({name}) => {
return <Counter name={name} initial={100} />
};
return (<div>
<button onClick={this.onButtonClick}>Change State</button>
<div>{`Flag: ${this.state.flag}`}</div>
<HundoCounter name="Component Def Inside render() - Hundo JSX"/>
{HundoCounter({name: 'Component Def Inside render() - Hundo Function Call'})}
<MilliCounter name="Component Def Outside render() - Milli JSX"/>
{MilliCounter({name: 'Component Def Outside render() - Milli Function Call'})}
</div>)
}
}
export default App;
import * as React from 'react'
export default class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: props.initial
}
}
onButtonClick = (event) => {
this.setState({
count: this.state.count + 1
})
};
render() {
return (
<div style={{border: '1px solid black', margin: '1rem', padding: '0.67rem'}}>
<h6>{this.props.name}</h6>
<p>Count: {this.state.count}</p>
<button onClick={this.onButtonClick}>Click Me</button>
</div>
)
}
}
这是显示演示应用程序运行的视频。 https://i.imgur.com/WfS8DXJ.mp4
如您所见,当单击按钮时,它会将标志更改为 true,从而强制重新渲染。 在此期间,JSX 定义的功能组件HundoCounter
的状态被重置,但不是直接调用的。
状态将重置对我来说很有意义,因为每次调用render()
时它都会创建HundoCounter
的新定义。 为什么直接作为函数调用的HundoCounter
的状态没有被重置?
我相信原因是因为您正在重新渲染父组件,然后当由于父组件重新渲染而重新渲染子组件时,它会重置 initial={100} 以将其设置回 100。
这是预期的行为
至于为什么第二个没有重置我不知道,但它没有重置似乎很奇怪,因为它的值也应该重置
好吧,这似乎很奇怪。 我认为这与 React 的reconciliation
and diff
算法有关。 当我将 key 属性添加到 Counter 组件时,它的行为符合我们的预期。
const HundoCounter = ({ name }) => {
console.log("hundo function")
return <Counter key={Math.random()} name={name} initial={100} />
};
我认为 render() 方法被调用并且 diff 算法在先前的结果和新结果上递归,并且以某种方式函数围绕组件并且表现得就像它是同一个组件。 顺便说一句,我喜欢这个实验:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.