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}&nbsp;
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 }

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章