为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第四天 context

标签:
React

课程:React18 系统精讲

章节:hooks

讲师:阿莱克斯刘

课程内容


今天,我学习了react的上下文对象,Context。先提个问题,在react项目中,我们如何传递变量?

打开 index.tsx 文件, 如果我们有个变量叫 username = “阿莱克斯“。一般来说,我们会通过使用props属性来传递变量,所以这时候我们可以给app组件创建一个username 的属性,然后把变量username传递给这个username prop。

打开app组件,给组件的Props interface 补充username的类型

interface Props {
	username: string}

然后在组件声明中补充范型,const App: React.FC<Props> = (props) => {, 。现在,我们就可以从这个参数props中获得从父组件传递来的username的数据了。如果想使用username,很简单,直接调用props.username就可以了。比如我们在网站header下面加上一个h2元素来展示username数据,<h2>{props.username}</h2>

好,打开命令行,npm start 启动网站看看结果是否正确。浏览器正确输出了我们从index传递给app组件的数据:阿莱克斯

我相信任何一个写过react代码的程序员都一定对这种props传递的机制非常非常了解。但是,如果我们想把“阿莱克斯”这个值传递给app的子组件,应该怎么做呢?

回到app组件中,在div里我加一个新的组件,叫<child />。这是时候,这个child组件想使用username,而不是app自己,那么我们就需要把username再向下传递一级。

<child username={props.username} />

这个机制将会以组件树的形式,将props自上而下传递给所有对username有需求的组件。于是就形成了props的深度注入,英文叫prop's drilling。通过这个例子,我们不难发现随着props注入越深,组件更新的频率也会愈来越高,而ui效率则会越来越慢,调试起来也会越来越困难。

于是我们就需要有别的方式来解决跨组件数据注入的问题,其中一个解决方案就是使用React的上下文context。React context允许我们的组件直接共享某个数据,而不是通过props注入的方式,这样就能避免出现props drilling。

请看具体实现:

  1. 首先,我们还原对app组件的修改,删除h2,删除interface中username的定义

  2. 回到index文件,删除app组件的username prpos

  3. 为了能够使用react context,我们首先得创建一个context

    const appConext = react.createContext()
  1. 不过,在创建上下文context的同时,react要求我们必须得先给定一个默认初始值。这个默认初始值是一个对象,可以叫做defaultContextValue 的对象,包含 username: “阿莱克斯”

    const defaultContextValue = {
        username: "阿莱克斯"
    }
  1. 接下来,为了能给app组件以及app的子组件提供数据支持,我们还需要设置一个provider来把整个render函数包裹起来。而provider的名字就是appConext .provide

        <appContext.Provider>
            <App />
        </appContext.Provider>
  1. 然后我们再把defaultContextValue注入provider的value props里面

		<appContext.Provider value={defaultContextValue}>
  1. 接下来,我们跳过app组件,进入它的子组件机器人画册Robot,那么在这个嵌套组件中我们如何获取username的数据呢?

    	import { appContext } from "../index";
    	<appContext.Consumer>
    	{(value) => (
    		<div className={styles.cardContainer}>
    			<img alt="robot" src={`https://robohash.org/${id}`} />
    			<h2>{name}</h2>
    			<p>{email}</p>
    			<p>作者:{value.username}</p>
    		</div>
    	)}
    	</appContext.Consumer>

  • 在渲染逻辑中加入数据的消费方式,使用consumer组件,组件内部使用花括号,只能在箭头函数内部使用共享数据。把之前的jsx渲染逻辑复制粘贴到Consumer内,我们给这个机器人画册组件的最后加一行代码,使用p tag,作者引用context中的内容,{value.username}

  • react有个特殊的词定义这个数据获取过程,叫做消费,英语consumer

  • 为了消费这个数据,首先需要Export 这个appContext

  • 然后回到Robot组件中引用appContext

好了,代码结束,保存一下文件,打开浏览器,刷新一下页面,正常输出了页面数据,不过,我们仔细观察一下机器人画册组件,我们会发现每张画册下面都加入一行新的作者数据,作者:阿莱克斯。而这个作者的数据就是通过react的上下文关系context传递的。

在react框架中通过provider和consumer来传递数据是一个非常受欢迎模式。但是随着react hooks的引入,于是我们也有了更加简单的方式在组件中消费数据,就是使用“useContex”钩子函数。请同学们打开robot.tsx

  • 在文件开头我们import一下 useContext

    	import React, {useContext} from "react";
  • 然后在robot组件的开头创建一下Consumer

    	const value = useContext(appContext)
  • 接下来,我们就能在return 中直接使用value了。请同学们去掉appContext.Consumer,相关的嵌套代码,去掉最外层的花括号,去掉value参数以及箭头函数,其他代码保持不变。

  • 好了,保存一下代码,重新编译网站,现在我们打开浏览器观察

  • 一切正常,数据输出没问题,而且每个机器人画册中依然保留着作者信息,作者:“阿莱克斯”

所以,就是这么简单,新加入的useContex hook 极大的减少了模版代码,降低了代码层级,也消灭了多个consumer嵌套的可能性。


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消