props, state 与 render 函数的关系
结合react的生命周期,我们知道: 当组件的state或者props发生改变的时候,render函数就会重新执行
使用Component有缺陷
来看下面这个demo:
import React, { Component } from 'react'
class Father extends Component {
constructor(props){
super(props)
this.state={
inputrValue:''
}
}
render() {
const { inputrValue } = this.state
console.log("Father render")
return (
<div>
<input type="text"
value={inputrValue}
onChange={e=>this.setState({inputrValue:e.target.value})}
/>
{/* 向子组件传递参数 */}
<Child content={inputrValue}/>
{/* 不传递任何参数 */}
<ChildA/>
</div>
)
}
}
class Child extends Component {
render() {
console.log("Child render")
return (
<div>Child: {this.props.content}</div>
)
}
}
class ChildA extends Component {
//当父组件被重新render时,会伴随着所有子组件的重新渲染
render() {
console.log("ChildA render")
return (
<div>ChildA</div>
)
}
}
export default Father
当页面第一次挂载的时候, 父组件和所有子组件的render函数都被执行了
我们在父组件的input输入框中输入'1'
发现父组件render函数执行了, 子组件的render函数也都执行了
接着,我们在父组件的input输入框中输入'2'
发现父组件render函数执行了, 子组件的render函数也都执行了,显然这不是我们期望的
使用PureComponent可以提高性能
父组件更新时,按理说子组件都会被重新渲染,倘若子组件很大,props又没发生改变,重新渲染子组件显然不科学
建议所有子组件都用PureComponent
(相当于函数式组件的memo
) 可以避免不必要的渲染 从而提高性能
import React, { Component, PureComponent } from 'react'
class Father extends PureComponent {
constructor(props){
super(props)
this.state={
inputrValue:''
}
}
render() {
const { inputrValue } = this.state
console.log("Father render")
return (
<div>
<input type="text"
value={inputrValue}
onChange={e=>this.setState({inputrValue:e.target.value})}
/>
{/* 向子组件传递参数 */}
<Child content={inputrValue}/>
{/* 不传递任何参数 */}
<ChildA/>
<ChildB/>
</div>
)
}
}
class Child extends PureComponent {
render() {
console.log("Child render")
return (
<div>Child: {this.props.content}</div>
)
}
}
class ChildA extends Component {
//当父组件的render函数被运行时,会伴随着所有子组件的重新渲染
render() {
console.log("ChildA render")
return (
<div>ChildA</div>
)
}
}
class ChildB extends PureComponent {
//当父组件的render函数被运行时,会伴随着所有子组件的重新渲染
render() {
console.log("ChildB render")
return (
<div>ChildB</div>
)
}
}
export default Father
当页面第一次挂载的时候, 父组件和子组件的render函数都执行了
我们在父组件的input输入框中输入'1'
发现父组件render函数执行了,子组件除了<ChildB/>
, 其他子组件的render函数都执行了
接着 我们在父组件的input输入框中输入'2'
发现父组件render函数执行了,子组件除了<ChildB/>
, 其他子组件的render函数都执行了
这是为什么呢?
- 首先,组件第一次挂载时会自动执行render函数
- 接着我们在input框输入
'1'
时,父组件的inputrValue
发生改变,导致父组件state发生改变,然后父组件重新render;父组件的重新render,会导致所有子组件的重新render,由于<Child/>
的content发生改变 也就是props发生改变,所以<Child/>
被重新render;但是<ChildB/>
没重新render,这是因为<ChildB/>
使用了PureComponent
, react只会检测state和props的变化而决定页面是否需要重新render, 然而<ChildB/>
state和props都没发生改变,所以页面没有刷新(相反<ChildA/>
不管数据是否变化,都会伴随父组件的render而render).这一切都能归功于虚拟dom,react底层的diff算法 - 然后输入
'2'
,原理都一样
问答
当父组件的render函数被运行时,它的子组件render都会伴随着父组件render而render吗?
答案:看情况
以下情况,子组件不会随父组件的render而被重新render,取决于state和props有没有发生改变
- 组件继承了
React.PureComponent
- 函数式组件用
memo
包裹 - 使用生命周期函数
shouldComponentUpdate
作了处理