React---新扩展Context和组件优化
一、Context
1. 理解
一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信
2. 使用
1) 创建Context容器对象:
const XxxContext = React.createContext()
2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
<xxxContext.Provider value={数据}>
子组件
</xxxContext.Provider>
3) 后代组件读取数据:
//第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
this.context // 读取context中的value数据
//第二种方式: 函数组件与类组件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显示的内容
)
}
</xxxContext.Consumer>
3. 注意
在应用开发中一般不用context, 一般都用它封装react插件
4. 代码
1 import React, { Component } from 'react' 2 import './index.css' 3 4 //创建Context对象 5 const MyContext = React.createContext() 6 const {Provider,Consumer} = MyContext 7 export default class A extends Component { 8 9 state = {username:'tom',age:18} 10 11 render() { 12 const {username,age} = this.state 13 return ( 14 <div className="parent"> 15 <h3>我是A组件</h3> 16 <h4>我的用户名是:{username}</h4> 17 <Provider value={{username,age}}> 18 <B/> 19 </Provider> 20 </div> 21 ) 22 } 23 } 24 25 class B extends Component { 26 render() { 27 return ( 28 <div className="child"> 29 <h3>我是B组件</h3> 30 <C/> 31 </div> 32 ) 33 } 34 } 35 36 /* class C extends Component { 37 //声明接收context 38 static contextType = MyContext 39 render() { 40 const {username,age} = this.context 41 return ( 42 <div className="grand"> 43 <h3>我是C组件</h3> 44 <h4>我从A组件接收到的用户名:{username},年龄是{age}</h4> 45 </div> 46 ) 47 } 48 } */ 49 50 function C(){ 51 return ( 52 <div className="grand"> 53 <h3>我是C组件</h3> 54 <h4>我从A组件接收到的用户名: 55 <Consumer> 56 {value => `${value.username},年龄是${value.age}`} 57 </Consumer> 58 </h4> 59 </div> 60 ) 61 }
二、optimize组件优化
1. Component的2个问题
1)只要执行setState(),即使不改变状态数据, 组件也会重新render()
2) 只当前组件重新render(), 就会自动重新render子组件 ==> 效率低
2. 效率高的做法
只有当组件的state或props数据发生改变时才重新render()
3. 原因
Component中的shouldComponentUpdate()总是返回true
4. 解决
方法1:
重写shouldComponentUpdate()方法
比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
方法2:
使用PureComponent
PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
注意:
只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
不要直接修改state数据, 而是要产生新数据
项目中一般使用PureComponent来优化
5. 代码
1 import React, { PureComponent } from 'react' 2 import './index.css' 3 4 export default class Parent extends PureComponent { 5 6 state = {carName:"奔驰c36",stus:['小张','小李','小王']} 7 8 addStu = ()=>{ 9 /* const {stus} = this.state 10 stus.unshift('小刘') 11 this.setState({stus}) */ 12 13 const {stus} = this.state 14 this.setState({stus:['小刘',...stus]}) 15 } 16 17 changeCar = ()=>{ 18 //this.setState({carName:'迈巴赫'}) 19 20 const obj = this.state 21 obj.carName = '迈巴赫' 22 console.log(obj === this.state); 23 this.setState(obj) 24 } 25 26 /* shouldComponentUpdate(nextProps,nextState){ 27 // console.log(this.props,this.state); //目前的props和state 28 // console.log(nextProps,nextState); //接下要变化的目标props,目标state 29 return !this.state.carName === nextState.carName 30 } */ 31 32 render() { 33 console.log('Parent---render'); 34 const {carName} = this.state 35 return ( 36 <div className="parent"> 37 <h3>我是Parent组件</h3> 38 {this.state.stus} 39 <span>我的车名字是:{carName}</span><br/> 40 <button onClick={this.changeCar}>点我换车</button> 41 <button onClick={this.addStu}>添加一个小刘</button> 42 <Child carName="奥拓"/> 43 </div> 44 ) 45 } 46 } 47 48 class Child extends PureComponent { 49 50 /* shouldComponentUpdate(nextProps,nextState){ 51 console.log(this.props,this.state); //目前的props和state 52 console.log(nextProps,nextState); //接下要变化的目标props,目标state 53 return !this.props.carName === nextProps.carName 54 } */ 55 56 render() { 57 console.log('Child---render'); 58 return ( 59 <div className="child"> 60 <h3>我是Child组件</h3> 61 <span>我接到的车是:{this.props.carName}</span> 62 </div> 63 ) 64 } 65 }