一. 父组件重新render
1.1直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染,无论props是否有变化。可通过shouldComponentUpdate方法优化。
class写法:
import React, {Component} from 'react'
class Child extends Component {
constructor(props) {
super(props)
}
// 直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染。
// 无论props是否有变化。可通过shouldComponentUpdate方法优化。
shouldComponentUpdate(nextProps) {
if(nextProps.data === this.props.data) return false
return true
}
render () {
return (
<div>
<hr></hr>
--- parent render ---
<br />
{console.log('child Render')}
{this.props.data}
</div>
)
}
}
export default Child
hook写法:
import React, {memo} from 'react'
const compare = (pre, cur) => {
// 甚至可以更详细的过滤指定对象
if(pre.data !== cur.data) return false
return true
}
// 使用memmo代替shouldComponentUpdate
const Child = memo((props) => {
return (
<div>
<hr></hr>
--- parent render hook 使用memo缓存---
<br />
{console.log('childHook Render')}
{props.data}
</div>
)
}, compare)
export default Child
1.2 在componentWillReceiveProps方法中,将props转换成自己的state
class写法:
import React, {Component} from 'react'
class Child extends Component {
constructor(props) {
super(props)
this.state = {
data: this.props.data
}
}
// 父组件重传props时就会调用这个方法
// 在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染。
// 是因为componentWillReceiveProps中判断props是否变化了,若变化了,this.setState将引起state变化,从而引起render,
// 此时就没必要再做第二次因重传props引起的render了,不然重复做一样的渲染了。
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps')
console.log(nextProps.data)
console.log(this.props.data)
// 其实不做判断也不会再次执行,貌似该函数自身已经做了判断。
if(nextProps.data != this.props.data) {
this.setState({data: nextProps.data})
}
}
render () {
return (
<div>
<hr />
--------propsToState componentWillReceiveProps组件提供props对比判断执行回调。---------
<br />
{console.log('propsToState Render')}
<p>
data: {this.state.data}
</p>
</div>
)
}
}
export default Child
hook写法:
import React, {useState, memo} from 'react'
const App = memo((props) => {
const [data, setData] = useState(props.data)
return (
<div>
<hr />
--------propsToStateHook 使用memo---------
<br />
{console.log('propsToStateHook Render')}
{data}
</div>
)
})
export default App
二,组件本身调用setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。
class写法:
import React, {Component} from 'react'
class Child extends Component {
constructor(props) {
super(props)
this.state = {
data: 1
}
}
// 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
shouldComponentUpdate(nextProps, nextState) {
if(nextState.data === this.state.data) return false
return true
}
render () {
return (
<div>
<hr />
--------self 设置对比---------
<br />
{console.log('selfSetState Render')}
{this.state.data}
<button onClick={() => this.setState({data: this.state.data})}>add</button>
<button onClick={() => this.setState({data: this.state.data + 1})}>add+1</button>
</div>
)
}
}
export default Child
hook写法:
import React, {useState} from 'react'
const Child = () => {
const [data, setData] = useState(1)
// 不改变data,没有组件重新渲染的问题。
const handleClick = () => {
setData(data)
}
return (
<div>
<hr />
--------selfhook 默认data不变不会自更新---------
<br />
{console.log('selfSetStateHook Render')}
{data}
<button onClick={handleClick}>add</button>
<button onClick={() => setData( data + 1)}>add + 1</button>
</div>
)
}
export default Child
注:
- react版本:17