让我带你迅速吃透React组件通信:从入门到精通(中篇)

在上篇文章中,我们介绍了React组件通信中最常用的父向子传值,和父组件通过回调函数获得子组件的数据,详情请看让我带你迅速吃透React组件通信:从入门到精通(上篇),以及父子直接通讯,本文将主要介绍兄弟组件之间的传值方式,以及context API跨层级共享方法

一、兄弟组件之间通过状态提升的方法进行通讯

1.什么是兄弟组件以及什么什么是状态提升 在 React 组件开发中,兄弟组件是指拥有同一个直接 / 间接父组件、但互相之间没有直接引用关系的同级组件。由于 React 组件的内部状态是私有隔离的,兄弟组件无法直接访问对方的 state、props 或实例方法,而状态提升(State Lifting) 正是 React 官方推荐的、解决兄弟组件通讯的原生标准方案,完全契合 React 单向数据流的核心设计理念。

由于兄弟组件之间没有直接的层级关系,所以他们不能像父子组件一样直接进行通讯,必须借助共同的父组件做为中转站来进行通讯,这就是转态提升

状态提升这一方法的核心思想就是:将兄弟组件之间需要共享的状态,先提供到他们最近的共同父组件中,然后父组件通过 props 分别传递给两个子组件,最终实现兄弟组件间的双向数据同步与通讯

简单来说,共同父组件就是兄弟组件之间的通讯中转站,所以数据流必须经过这个中转站,没有任何私有的直接通讯

2. 实际用例

3.什么时候选择该方法进行通讯,为什么?

  1. 该方法在兄弟组件之间层级不深的情况下适用,逻辑清晰,易于使用
  2. 不需要而外引入任何库,原生支持
  3. 若兄弟组件之间嵌套的层级过深,或者需要共享的状态很多,则不适合使用,因为由于Prop Driling会导致父组件变得很臃肿,且需要进行多层传递

介绍Context API之前,先让我们了解了解Prop Drilling到底有多恶心?

1.举一个真实开发时会遇到的场景,当全局主题色需要根据从根组件App,传递给 Layout → Header → Nav → UserAvatar 这四层嵌套组件,只有最底层的 UserAvatar需要使用该主题时,中间三层组件都要写冗余的Props透传代码,一旦主题变量改名,所有的中间层都要进行修改,极易出现错误。这就是典型的Drilling场景,也就是我们使用Context API的目的:跳过中间层,实现顶层数据到底层数据的直接共享

二、 Context API跨组件通讯方法

由于兄弟组件之间使用状态提升方法容易形成多层嵌套,导致父组件臃肿且传递困难,于是React提供了Context API跨组件通讯方法来解决这个问题,类似于将需要传递的信息添加为全局变量。

  1. 为了方便理解,我们可以将这个方法比喻为快递的传递来形容
  • createContext 用于创建一个「快递站」的角色,可以设定默认值
  • Provide: 用于给指定区域的组件「派送包裹」 ,通过value 属性传递数据
  • Consumer/useContext:「领取包裹的方法」(Hook更常用)
  • contextType: 类组件中Context的专用属性

以「主题切换」为例,演示从创建 Context 到消费数据的全流程:

1.创建Context(定义共享数据的容器)

2.搭载Provider(包裹需要共享数据的组件树)

在顶层组件(如APP.js)中挂载Provider,让后代组件能够访问主题数据

3.使用Context(一般使用useContext):

其实,Context在这组件传递当中就类似于一个仓库的样子,将需要被派送的组件放在Provider这个派送区域,便可将需要派送的包裹派送往该派送区域内的组件中。

在使用Context API时需要注意的点:
  1. 只有当组件没有被对应的Provider包裹时,才会使用 createContext 的默认值,即使Provider 的value 为undefined的时候也不会触发该默认值
  2. 当Provider 的value 变化时,所有使用该 Context 的组件都会被重新渲染,因此:
  • 我们可以使用 useCallback 缓存方法,避免方法引用频繁变化
  • 或使用 usememo方法 缓存 value 对象,仅当依赖项变化时我们才更新
  1. 我们可以同时使用多个Provider 嵌套,分别提供不同的共享数据(如主题,用户信息),他们之间并不会互相起冲突
  2. 当value需要频繁变化时,(Context)重渲染的成本高、浅层组件通讯更高效(比如props)
Contex适用和不适应的场景:

适用场景:

使用在跨多层组件需要共享数据时(如主题、语言、用户登录状态)、小型应用的转态管理(无需引入Redux/Zustand)

不适用的场景: 高频更新状态:实时表单数据,滚动位置,倒计时等 购物车,数据流,大量异步请求等

Context频繁重渲染问题:

由于Context API 的value 只要发生引用变化,所有使用该 Context 的组件都会强制重新渲染,哪怕组件只用到了 value 的一小部分数据 比如 value 里包含 theme 和 user 两个数据,仅 user 变更, 使用 theme 的组件也会重新渲染,造成性能浪费,对于该问题,我们有两个较好的优化方案

1. 拆分 Context (可从根源解决)

不要把所有共享状态塞到一个大的 Context里,根据数据更新频率、业务关联性拆分成多个小的Context。比如低频更新的主题和语言拆成一个,高频更新的用户信息、购物车等内容拆成独立的Context。

2.使用 usememo缓存 value (基础优化)

每次父组件渲染时,直接写在Provider里的对象会被重新渲染,导致 value引用发生变化。用useMemo 缓存 value ,仅依赖项变更时才会更新,避免无效的重新渲染

相关推荐
大圣编程1 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang1 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆2 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜3 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞4 小时前
异步HttpModule的实现方式
java·服务器·前端
黄敬峰5 小时前
🚀 从 Prompt 到 Harness:AI 编程的下半场,我们如何给大模型套上“挽具”?
面试
用户852495071845 小时前
手搓自然语义搜索:从传统匹配到向量化,理解 RAG 的第一步
面试
YFF菲菲兔5 小时前
其他 Hooks 解析
react.js
C语言小火车5 小时前
C++ 快速排序(Quick Sort)深度精讲:分治思想、Lomuto 分区法及三数取中优化,面试手撕必会
c语言·开发语言·c++·面试·排序算法·快速排序