3. context和optimize优化
3.1 context
context用于祖孙组件之间的传参
import React, {Component} from 'react';
import './index.css'
// 创建一个context组件,供传递数据使用
const MyContext = React.createContext()
class A extends Component {
state = {username: 'cxk', age:18}
render() {
const {username} = this.state
return (
<div className='parent'>
<h3>我是A组件</h3>
<h4>我的用户名是:{username}</h4>
{/* 固定写法*/}
<MyContext.Provider value={this.state}>
<B/>
</MyContext.Provider>
</div>
);
}
}
//第一种方式:仅适用于类组件
class B extends Component {
// 声明使用contex,才能获取到祖组件传递的数据
static contextType = MyContext
render() {
// 读取context中的value数据
// console.log(this.context)
return (
<div className='child'>
<h3>我是B组件</h3>
<h4>我从A接收到的用户名是:{this.context.username}</h4>
<C/>
</div>
);
}
}
// class C extends Component {
// // 声明使用contex,才能获取到祖组件传递的数据
// static contextType = MyContext
//
// render() {
// // console.log(this)
// return (
// <div className='grand'>
// <h3>我是C组件</h3>
// <h4>我从A收到的用户名是:{this.context.username}, 年龄是{this.context.age}</h4>
// </div>
// );
// }
// }
//第二种方式: 函数组件与类组件都可以
function C() {
return (
<div className='grand'>
<h3>我是C组件</h3>
<h4>我从A收到的用户名是:
{/*函数式组件使用context取值, 类式组件也可以*/}
<MyContext.Consumer>
{
(value)=>{ // value就是context中的value数据
return `${value.username} 年龄是:${value.age}`
}
}
</MyContext.Consumer>
</h4>
</div>
);
}
export default A;
注意
在应用开发中一般不用context, 一般都用它的封装react插件
3.2 optimize优化
Component的2个问题
只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低
只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据 ==> 效率低
效率高的做法
只有当组件的state或props数据发生改变时才重新render()
原因
Component中的shouldComponentUpdate()总是返回true
解决
办法1:
重写shouldComponentUpdate()方法
比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
办法2:
使用PureComponent
PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
注意:
只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
不要直接修改state数据, 而是要产生新数据
项目中一般使用PureComponent来优化
import React, {Component, PureComponent} from 'react';
import './index.css'
class Parent extends PureComponent {
state = {carName: 'BMW', stus:['a','b','c']}
addStu = () => {
// 错误
/* const {stus} = this.state
stus.unshift('老王')
this.setState({stus})*/
// 正确
const {stus} = this.state
this.setState({stus:['老王',...stus]})
}
changeCar = () => {
// this.setState({})
// 使用PureComponent后不能在原来得对象修改,不然就视为没有更新 ,所以点击并没有触发render,
// const obj = this.state
// obj.carName = 'AMG'
// this.setState(obj)
// 正确
this.setState({carName: 'AMG'})
}
// shouldComponentUpdate(nextProps, nextState, nextContext) {
// console.log(nextProps,nextState)
// console.log(this.props,this.state)
// return !(nextState.carName === this.state.carName)
// }
render() {
console.log('parent---render')
const {carName} = this.state
return (
<div className='parent'>
<h3>我是Parent组件</h3>
<span>{this.state.stus} </span>
<span>我的车现在是{carName}</span>
<button onClick={this.changeCar}>点我换车</button>
<button onClick={this.addStu}>添加一个老王</button>
<Child carName={carName}/>
</div>
);
}
}
class Child extends PureComponent {
// shouldComponentUpdate(nextProps, nextState, nextContext) {
// // console.log(nextProps,nextState)
// // console.log(this.props,this.state)
// return !(nextProps.carName === this.props.carName)
// }
render() {
// 使用PureComponent后若子组件的数据没更新就不会触发render
console.log('child---render')
return (
<div className='child'>
<h3>我是Child组件</h3>
<span>我接到的车是{this.props.carName}</span>
</div>
);
}
}
export default Parent;