React学习笔记——Hooks中useContext的基础介绍和使用

在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我们依赖于类组件来获取数据,处理数据,并向下传递参数给 UI 组件进行渲染。使用 React Hooks 相比于从前的类组件有以下几点好处:

  1. 代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护
  2. 组件树层级变浅,在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,而在 React Hooks 中,这些功能都可以通过强大的自定义的 Hooks 来实现

Hook 是 React 16.8.0 版本增加的新特性,可以在函数组件中使用 state以及其他的 React 特性
Hooks只能在函数式组件中使用,既无状态组件(所有钩子在用时都要先引入)

1、Hook 使用规则

Hook 就是JavaScript 函数,但是使用它们会有两个额外的规则:
1、只能在函数最外层调用 Hook。不要在循环、条件判断或者嵌套函数(子函数)中调用。
2、只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
3、在多个useState()调用中,渲染之间的调用顺序必须相同

2、useContext
(1)作用
  1. Context 提供了一个无需为每层组件手动添加的 props,就能在组件树间进行数据传递的方法。
  2. Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。
(2)使用方法
const value = useContext(MyContext);
  1. 先使用 createContext 创建一个 Context对象。
  2. 再使用 useContext来接收一个 context 对象(React.createContext 的返回值),并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的<MyContext.Provider> 的 value prop决定。

当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值

注意:即使祖先使用 React.memoshouldComponentUpdate也会在组件本身使用 useContext 时重新渲染

别忘记 useContext 的参数必须是 context 对象本身

  • 正确: useContext(MyContext)
  • 错误: useContext(MyContext.Consumer)
  • 错误: useContext(MyContext.Provider)
(3)useContext实例一

在这里插入图片描述
DemoContext.js组件——创建一个Context对象

import React , {createContext} from 'react'

const DemoContext = createContext()

export default DemoContext

Demo1.js(爷爷组件)——利用Context的Provider注入value属性

import React,{useState} from 'react';
import DemoContext from './DemoContext'
import Demo2 from './Demo2'

const Demo1 = () => {
    const [ num , setNum ] = useState(0)
    const handleAddClick = () => {
        setNum(num=>num+1)
    }
    const handleSubClick = () => {
        setNum(num => num -1)
    }
    return (
    	console.log('爷爷组件'),
        <div style={{backgroundColor:'yellow'}}>
            <h1 >爷爷组件</h1>
            <DemoContext.Provider value={{num , handleAddClick , handleSubClick}}>
                {num} <br/>
                <Demo2></Demo2>
            </DemoContext.Provider>
        </div>
    );
};

export default Demo1;

Demo2.js(爸爸组件)

import React from 'react';
import Demo3 from './Demo3'
const Demo2 = () => {
    return (
        <div style={{backgroundColor:'yellowGreen'}}>
            <h2>爸爸组件</h2>
            <div>
                <Demo3></Demo3>
            </div>
        </div>
    );
};

export default Demo2;

Demo3.js(儿子组件)——useContext读取Context对象,拿到传递的value

import React ,{useContext}from 'react';
import DemoContext from './DemoContext'

const Demo3 = () => {
    const aaa = useContext(DemoContext)
    console.log('111',aaa ) // 111 {num: 0, handleAddClick: ƒ, handleSubClick: ƒ}
    return (
    	console.log('儿子组件',aaa ),
        <div style={{backgroundColor:'pink'}}>
            <h3>儿子组件</h3>
            <div>
                <button onClick={aaa.handleSubClick}>-</button>
                {aaa.num}
                <button onClick={aaa.handleAddClick}>+</button>
            </div>
        </div>
    );
};

export default Demo3;

在这里插入图片描述

(4)useContext实例二

与实例一相似,不过实例二把Context对象Provider单独抽取出来

MyContext.js ——创建Context对象;利用Provider注入value;向外暴露

import React , {createContext, useState} from 'react';

const MyContext = createContext()

const Context = (props) => {
    const [ num , setNum ] = useState(0)
    const handleAddClick = () => {
        setNum(num=>num+1)
    }
    const handleSubClick = () => {
        setNum(num => num -1)
    }
    return (
        <MyContext.Provider 
            value={{num,handleAddClick,handleSubClick}}
        >
            {props .children}
        </MyContext.Provider>
    );
};

export {
    Context,
    MyContext
} ;

Demo1.js(爷爷组件)——引入的Provider函数,包裹在最外层

import React, { useState } from 'react';
import {Context} from './Context'
import Son from './Son'
const GrandFather = () => {
    return (
        <Context>
            <div>我是爷爷</div>
            <Son></Son>
        </Context>
    );
};

export default GrandFather;

Demo2.js(爸爸组件)

import React from 'react';
import Children from './Children'
const Son = () => {
    return (
        <div>
            我是儿子
            <Children></Children>
        </div>
    );
};

export default Son;

Demo3.js(儿子组件)——useContext读取Context对象,拿到传递的value

import React , {useContext }from 'react';
import {MyContext} from './Context'

const Children = (props) => {
    const bbb = useContext(MyContext)
    console.log('bbb',bbb)
    return (
        <div>
            <h3>我是孙子</h3>
            
            <div>
                <button onClick={bbb.handleAddClick}>+</button>
                num:{bbb.num}
                <button onClick={bbb.handleSubClick}>-</button>
            </div>
        </div>
    );
};

export default Children;

效果图
在这里插入图片描述

(5)多层嵌套Context

以实例一为准,多添加一个名字为TemContext的Context对象

DemoContext.js——组件向外暴露两个Context对象(DemoContext和TemContext)

import React , {createContext} from 'react'

const DemoContext = createContext()
const TemContext = createContext()

export {
    DemoContext,
    TemContext
} 

Demo1.js ——两个Context的Provider互相嵌套

import React,{useState} from 'react';
import {DemoContext,TemContext} from './DemoContext'
import Demo2 from './Demo2'

const Demo1 = () => {
    const [ num , setNum ] = useState(0)
    const [ val , setVal ] = useState({name:'张三'})
    const handleAddClick = () => {
        setNum(num=>num+1)
    }
    const handleSubClick = () => {
        setNum(num => num -1)
    }
    return (
        console.log('爷爷组件'),
        <div style={{backgroundColor:'yellow'}}>
            <h1 >爷爷组件</h1>
            <DemoContext.Provider value={{num , handleAddClick , handleSubClick}}>
                <TemContext.Provider value={val}> 
                    {num} <br/>
                    <Demo2></Demo2>
                </TemContext.Provider>
            </DemoContext.Provider>
        </div>
    );
};

export default Demo1;

Demo2.js —— 没变

import React from 'react';
import Demo3 from './Demo3'
const Demo2 = () => {
    return (
        <div style={{backgroundColor:'yellowGreen'}}>
            <h2>爸爸组件</h2>
            <div>
                <Demo3></Demo3>
            </div>
        </div>
    );
};

export default Demo2;

Demo3.js —— 利用useContext读取两个Context对象,进行操作

import React ,{useContext}from 'react';
import {DemoContext ,TemContext}from './DemoContext'

const Demo3 = () => {
    const aaa = useContext(DemoContext)
    const bbb = useContext(TemContext)
    return (
        console.log('儿子组件',aaa ),
        console.log('bbb',bbb),
        <div style={{backgroundColor:'pink'}}>
            <h3>儿子组件</h3>
            <div>
                <button onClick={aaa.handleSubClick}>-</button>
                    <div>DemoContext的:{aaa.num}</div>
                    <div>TemContext的:{bbb.name}</div>
                <button onClick={aaa.handleAddClick}>+</button>
            </div>
        </div>
    );
};

export default Demo3;

效果图 (可以正常使用)
在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值