举个例子说明,父组件触发 render,无论子组件使用到父组件的 state 作为 props 值是否改变,甚至无论子组件是否使用到父组件的 state,都会触发子组件 render
class ChildOne extends React.Component {
constructor(props) {
super(props)
}
render() {
const {value} = this.props;
console.log('触发子组件 ChildOne 的 render')
return (
<div className="box">
<p> 子组件 ChildOne</p>
<div> 父组件传入 props 数据{value}</div>
</div>
);
}
}
class ChildTwo extends React.Component {
constructor(props) {
super(props)
}
render() {
console.log('触发子组件 ChildTwo 的 render')
return (
<div className="box">
<p> 子组件 ChildTwo</p>
</div>
);
}
}
class App extends React.Component {
state = {
value: 1,
};
handleClick = () => {
this.setState({
value: 1
});
};
render() {
console.log('触发父组件的 render')
return (
<React.Fragment>
<div className="box">
<div>{this.state.value}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
<ChildTwo/>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
对于 react 的 class 组件,我们可以使用 PureComponent 处理基本数据类型
class ChildOne extends React.PureComponent {
constructor(props) {
super(props)
}
render() {
const {value} = this.props;
console.log('触发子组件 ChildOne 的 render')
return (
<div className="box">
<p> 子组件 ChildOne</p>
<div> 父组件传入 props 数据{value}</div>
</div>
);
}
}
class ChildTwo extends React.PureComponent {
constructor(props) {
super(props)
}
render() {
console.log('触发子组件 ChildTwo 的 render')
return (
<div className="box">
<p> 子组件 ChildTwo</p>
</div>
);
}
}
class App extends React.Component {
state = {
value: 1,
};
handleClick = () => {
this.setState({
value: 1
});
};
render() {
console.log('触发父组件的 render')
return (
<React.Fragment>
<div className="box">
<div>{this.state.value}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
<ChildTwo/>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
PureComponent,浅比较只能比较基本数据类型的异同,如果传入的 props 是复杂数据类型 子组件render仍然会触发 举个例子
class ChildOne extends React.PureComponent {
constructor(props) {
super(props)
}
render() {
const {value} = this.props;
console.log('触发子组件 ChildOne 的 render')
return (
<div className="box">
<p> 子组件 ChildOne</p>
<div> 父组件传入 props 数据{value.number}</div>
</div>
);
}
}
class App extends React.Component {
state = {
value: {
number: 1,
}
};
handleClick = () => {
this.setState({
value: {
number: 1
}
});
};
render() {
console.log('触发父组件的 render')
return (
<React.Fragment>
<div className="box">
<div>{this.state.value.number}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
shouldComponentUpdate 处理复杂数据类型
class ChildOne extends React.Component {
constructor(props) {
super(props)
}
shouldComponentUpdate(nextProps, nextState) {
console.log('nextProps', nextProps)
console.log('this.props', this.props)
return nextProps.value.number !== this.props.value.number
}
render() {
console.log('触发子组件 ChildTwo 的 render')
return (
<div className="box">
<p> 子组件 ChildTwo</p>
</div>
);
}
}
class App extends React.Component {
state = {
value: {
number: 1,
}
};
handleClick = () => {
this.setState({
value: {
number: 1
}
});
};
render() {
console.log('触发父组件的 render')
return (
<React.Fragment>
<div className="box">
<div>{this.state.value.number}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
前面是 class 组件的优化方式,那么对于函数式组件,我们又该如何处理呢?
react 很贴心的提供了 React.memo() 高阶组件,他的功能与 PureComponent 类似: 以下例子 ChildOne 触发render ChildTwo 不触发render
const ChildOne = props => {
console.log('触发子组件 ChildOne 的 render')
return (
<div className="box">
<p> 子组件 ChildOne</p>
<div> 父组件传入 props 数据{props.value.number}</div>
</div>
)
};
const ChildTwo = React.memo(() => {
console.log('触发子组件 ChildTwo 的 render')
return (
<div className="box">
<p> 子组件 ChildTwo</p>
</div>
)
})
class Home extends React.Component {
state = {
value: {
number: 1,
},
};
handleClick = () => {
this.setState({
value: {
number: 1,
},
});
};
componentDidMount() {}
render() {
// return <div className="test">Home</div>;
console.log("触发父组件的 render");
return (
<React.Fragment>
<div className="box">
<div>{this.state.value.number}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
<ChildTwo/>
</React.Fragment>
);
}
}
React.memo() 高阶组件处理复杂类型
const ChildOne = React.memo(props => {
console.log('触发子组件 ChildTwo 的 render')
return (
<div className="box">
<p> 子组件 ChildOne</p>
<div> 父组件传入 props 数据{props.value.number}</div>
</div>
)
}, areEqual)
function areEqual(prevProps, nextProps) {
console.log('prevProps', prevProps)
console.log('nextProps', nextProps)
return prevProps.value.number === nextProps.value.number
}
class App extends React.Component {
state = {
value: {
number: 1,
}
};
handleClick = () => {
this.setState({
value: {
number: 1
}
});
};
render() {
console.log('触发 render')
return (
<React.Fragment>
<div className="box">
<div>{this.state.value.number}</div>
<button onClick={this.handleClick}>+</button>
</div>
<ChildOne value={this.state.value}/>
</React.Fragment>
);
}
}
ReactDOM.render(<App/>, document.getElementById("root"))
总结xmind图