Skip to main content

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作了处理