react context 使用方法 + hooks版本 + class类版本( 不比react-redux香吗? )

  最近写了一个组件,发现别人传递参数后,组件逐层传递数据(props)太麻烦了,而且我也不需要改变根组件的状态值,也不想使用redux,

突然发现 context 很适合使用( 跨层级传递数据 )

 

今天就介绍下context(执行的上下文)

  我们和网上的案例不一样,我们分文件写代码,写在不同的js里面(更符合实际,网上的案例10个9复制),下面有实例(hooks版本的)

使用步骤

  1、使用 React.CreateContext() 创建context 

  2、React.Provider标签包裹想要分享组件的父组件,value传递你要分享的数据(可以写成对象形式),例:value:{{ name:"张三",changeNameHandle: changeNameHandle }}

  3、子代组件使用分享的数据:React.Consumer包裹需要使用数据的组件,然后使用 { value =>  { return ( 你要展示的结构 ) } },包裹你要展示的结构,下方Children.js有红色标记

  效果

 

 

 孙子组件想用劳资组件的数据

hooks版本

  1、context.js(建立一个context文件,这样声明的context就可以随时引用)  

1 import React from "react";
2 const MyContext =   React.createContext();
3  // 常见一个context,并把 Provider 和 Consumer 暴露出去
4 export const { Provider,Consumer } = MyContext;

  2、Labor.js

 1 import React, { useState } from "react";
 2 // 引入声明的context
 3 import { Provider } from './context';
 4 import Far from './Far';
 5 
 6 const Labor = () => {
 7     const [value,changeValue] = useState(1);  //随便声明一个变量
 8     
 9     // 声明的一个函数,可以在这个函数里改变useState声明的变量操作
10     const handleChange = (data) => {
11         // 例如孙子组件点击一下  value + data
12         changeValue(value + data)
13       }
14 
15     return (
16         <Provider 
17                 value={{ value:value,handleChange:handleChange }}
18         >
19           <div style={{ backgroundColor:"#6fe6df",padding:35 }}>
20             劳资组件
21             <Far />
22 
23       </div>
24     </Provider>
25     )
26 }    
27 
28 export default Labor;    

  3、Far.js

  

import React from "react";
import Children from './Children';

const Far = () => {

  return (
    <div style={{ backgroundColor:"#f54110",padding:50  }}>
      父亲组件
      <Children />
    </div>
  )

}

export default Far ; 

  4、Children.js

import React from "react";
import { Button } from 'antd'
// 引入consumer
import { Consumer } from './context';

const Children = () => {

  return (
    <Consumer>
      {
        value => {
          return (
            <div style={{ backgroundColor:"#65f781",padding:20  }}>
        
                  孙子组件{value.value}
                  <Button 
                    type="primary" 
              //调用劳资组件传递过来的方法
                    onClick={()=>value.handleChange(1)}
                  >
                    尝试改变
                </Button>

            </div>
          )
        }
      }
      
    </Consumer>
  )

}

export default Children ; 

 

其实很简单:

    Provider包裹父组件,并把需要分享的数据给到Provider标签中value属性,

    后面的子代谁想使用分享的数据,就用Consumer标签包裹,并用 { value => { return (   原本组件的结构  ) } },使用分享的数据就在里面 value.属性 

   

class类的组件使用 context 会有点不一样

  1、MyContext.js

1 import React from "react";
2 export const MyContext =   React.createContext();

  2、Labor.js

 1 import React, { useState } from "react";
 2 // 引入声明的context
 3 import { MyContext } from './context';
 4 import Far from './Far';
 5 
 6 const Labor = () => {
 7     const [value,changeValue] = useState(1);  //随便声明一个变量
 8     
 9     // 声明的一个函数,可以在这个函数里改变useState声明的变量操作
10     const handleChange = (data) => {
11         // 例如孙子组件点击一下  value + data
12         changeValue(value + data)
13       }
14 
15     return (
16         <MyContext.Provider  
17                 value={{ value:value,handleChange:handleChange }}
18         >
19           <div style={{ backgroundColor:"#6fe6df",padding:35 }}>
20             劳资组件
21             <Far />
22 
23       </div>
24     </MyContext.Provider >
25     )
26 }    
27 
28 export default Labor; 

  3、Far.js

import React from "react";
import Children from './Children';

const Far = () => {

  return (
    <div style={{ backgroundColor:"#f54110",padding:50  }}>
      父亲组件
      <Children />
    </div>
  )

}

export default Far ; 

  4、Children.js

import React, { Component } from 'react';
import { Button } from 'antd';
import { MyContext } from '../../../context';

export default class Children extends Component {

  static contextType = MyContext;
  render() {
    return (
      <div style={{ backgroundColor:"#65f781",padding:20  }}>
        
        孙子组件{this.context.value}
        <Button 
          type="primary" 
          onClick={()=>this.context.handleChange(1)}
        >尝试改变</Button>
      </div>
    )
  }
}

或者

import React, { Component } from 'react';
import { Button } from 'antd';
import { MyContext } from '../../../context';

export default class Children extends Component {

  render() {
    return (
      <MyContext.Consumer>
        {
          value => {
            return (
              <div style={{ backgroundColor:"#65f781",padding:20  }}>
        
                孙子组件{value.value}
                <Button 
                  type="primary" 
                  onClick={()=>value.handleChange(1)}
                >尝试改变</Button>
              </div>
            )
          }
        }
      </MyContext.Consumer>
    )
  }
}

 

Redux和Context对比

如果项目体量较小,只是需要一个公共的store存储state,而不讲究使用action来管理state,那context完全可以胜任。反之,则是redux的优点。

context的缺点

  • React 新特性 context 在大型数据应用的前提下,并不会减少模版代码。而其 Provider 和 Consumer 的一一对应特性,即 Provider 和 Consumer 必须来自同一次 React.createContext 调用(可以用 hack 方式解决此“局限”)
  • 因为没有了action,state的值都是被直接修改,state的数据安全性不及redux。
  • 不能使用redux的中间件,比如thunk/saga,在一些异步的情况需要自己来处理。

 

posted @ 2021-08-26 16:54  HandsomeGuy  阅读(368)  评论(0编辑  收藏  举报