在业务中使用React,不可避免地会遇到需要各种组件之间进行通信的情况,这些情况总结起来大概分为以下几种:
- 父组件向子组件通信
- 子组件向父组件通信
- 跨级组件通信
- 非嵌套组件之间通信
父组件向子组件通信
这是最简单也是最常用的一种组件通信方式,父组件通过props将信息传递给子组件,子组件在接收到props后进行相应的操作。
父组件Parent.tsx
1 | import React, {useEffect, useState} from 'react'; |
子组件Child.tsx
1 | import React from 'react'; |
在上面例子中,父组件定义了message,并将其作为props传递给子组件,子组件接收props,并将其显示。
子组件向父组件通信
在某些情况中,当子组件的某些值改变,也需要通知父组件做出某些操作或改变。React中遵循单向数据流的原则,不可以直接通过改变props的值来达到改变父组件值的目的,正确的使用方式是:父组件将一个函数作为props传递给子组件,子组件调用该函数来与父组件通信。
父组件Parent.tsx
1 | import React, {useEffect, useState} from 'react'; |
子组件Child.tsx
1 | import React from 'react'; |
在上面例子中,父组件定义了changeMessag方法,并将其作为props传递给子组件,子组件接收props,当子组件点击按钮的时候执行props中的changeMessag方法,改变父组件中message的值。
跨级组件通信
所谓跨级组件通信,就是指父组件向子组件的子组件通信,向更深层的子组件通信。跨级组件通信可以采用下面两种方式:
- 通过props一层一层向下传递
- 使用context对象
对于第一种方式,如果组件嵌套的层次比较深,中间的每一层组件都要传递props;缺点是显而易见的,增加了程序的复杂度,而且对于中间层组件来说,这些props并不是自己所需要的,增加冗余代码,使代码并不十分友好,所以如果嵌套的层次比较深的话,斟酌使用这种方式。
使用context对象时另一种解决跨组件通信的方式,context相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。相对于第一种通信方式,这种方式显得更加友好。
myContext.ts——上下文管理的组件,用来统一导出 Context 实例
1 | import React from 'react' |
父组件Parent.tsx
1 | import React, {useState, createContext} from 'react'; |
子组件Child.tsx
1 | import React from 'react'; |
孙子组件GrandChild.tsx
1 | import React, {useContext} from 'react' |
以上例子中,父组件使用上下文MyContext,并给其赋值message为当前组件的state变量message,changeMessage为当前组件定义的变量changeMessage,用于改变message的值。在孙子组件中,也引入MyContext上下文,并将其作为useContext的参数,从而得到父组件中的message和changeMessage。在孙子组件中点击按钮,直接调用MyContext透传过来的方法,可以修改父组件的message,孙子组件则会重新渲染。这种方式显式的避免了多级 props 的层层透传问题,对于嵌套层次比较深的组件是比较方便的。
非嵌套组件之间通信
非嵌套组件,就是没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。对于非嵌套组件,可以利用二者共同父组件的 context 对象进行通信。