React 组件通讯全攻略:拒绝 "Props" 焦虑,掌握数据流动的艺术

前言

React 的开发旅程中,组件就像是乐高积木,我们把它们一个个搭起来构建出复杂的页面。但光搭起来还不够,这些积木之间必须有"电流"流通------这就是数据。
React 的设计哲学是单向数据流,就像瀑布一样,水流默认只能从高处流向低处。但在实际业务中,我们经常需要逆流而上,或者在两个平行的水池间交换水流。今天我们就来盘点 React 中最主流的四种"引水"方式,打通你的组件经脉。


1. 父传子:顺流而下的 Props

这是 React 中最自然、最基础的通信方式。想象一下,父亲给孩子零花钱,父亲(父组件)只需要要把钱(数据)递过去,孩子(子组件)伸手接着就行。

在代码层面,父组件通过在子组件标签上写上自定义属性(msg)来传递数据。

jsx 复制代码
import Child from "./Child"
export default function Parent() {
  const state = {
    name: '小饶'
  }
  
  return (
    <div>
      <h2>父组件</h2>
      {/* 父亲把 '小饶' 这个名字打包进 msg 属性传给孩子 */}
      <Child msg={state.name} />
    </div>
  )
}

孩子组件这边,所有接收到的礼物都装在一个叫 props 的盒子里。不过要注意,Props 是只读的------这意味着孩子只能使用这些数据,不能直接修改它。就像孩子不能自己修改父亲银行卡的余额一样,如果要改,必须请求父亲操作。

jsx 复制代码
export default function Child(props) {
  // 打开盒子看看收到了什么
  console.log(props);
  
  return (
    <h3>子组件 -- {props.msg}</h3>
  )
}

2. 子传父:给孩子一个"遥控器"

既然水流默认向下,那子组件想要改变父组件的数据该怎么办?比如,孩子想告诉父亲:"我考了 100 分,请更新一下你的心情状态"。

这时候,父组件需要提前准备一个"遥控器"------也就是一个函数。父组件把这个函数通过 props 传给子组件,当子组件需要通信时,就按下这个遥控器(调用函数),并把数据作为参数传回去。 **父组件: 准备好 getNum 函数,用来接收数据并更新自己的 count。 **

jsx 复制代码
import Child from "./Child"
import { useState } from 'react'

export default function Parent() {
  let [count, setCount] = useState(1)  

  // 这就是那个"遥控器"函数
  const getNum = (n) => {
    setCount(n)
  }

  return (
    <div>
      <h2>父组件二 -- {count}</h2>
      {/* 把遥控器交给孩子 */}
      <Child getNum={getNum}></Child>
    </div>
  )
}

子组件: 在合适的时机(比如点击按钮时),通过 props 拿到并按下这个"遥控器"。

jsx 复制代码
export default function Child(props) {
  
  const state = {
    num: 100
  }

  function send() {
    // 此时调用的是父组件里的函数,把 100 传了回去
    props.getNum(state.num)
  }

  return (
    <div>
      <h3>子组件二</h3>
      <button onClick={send}>发送</button>
    </div>
  )
}

3. 兄弟组件:找个共同的"家长"

兄弟组件之间没有直接的连线,就像你和你的表弟住在不同的屋子里,想聊天得通过大厅里的长辈传话。 这种模式在 React 中通常被称为状态提升。既然 Brother1 想要给 Brother2 传值,那我们就把这个值保存在他们共同的父亲身上。

  • Brother1 -> Parent:Brother1 先把数据传给父亲(利用上面的子传父技巧)。
  • Parent -> Brother2:父亲拿到数据后,更新自己的状态,再把这个新状态顺手传给 Brother2(利用父传子技巧)。

父组件(中间枢纽):

jsx 复制代码
import { useState } from "react"
import Child1 from "./Child1"
import Child2 from "./Child2"

export default function Parent() {
  let [message, setMessage] = useState()

  // 接收老大传来的消息
  const getMsg = (msg) => {
    setMessage(msg)
  }

  return (
    <div>
      <h2> 父组件三 </h2>
      {/* 接收者:从 Child1 收信 */}
      <Child1 getMsg={getMsg} />
      {/* 发送者:把信转交给 Child2 */}
      <Child2 message={message} />
    </div>
  )
}

Child1(消息发送方):

jsx 复制代码
export default function Child1(props) {
  const state = {
    msg: '1 中的数据'
  }

  function send() {
    props.getMsg(state.msg)
  }
  
  return (
    <div>
      <h3>子组件1</h3>
      <button onClick={send}>1</button>
    </div>
  )
}

Child2(消息接收方):

jsx 复制代码
export default function Child2(props) {
  return (
    <div>
      {/* 坐等父亲把兄弟的消息送过来 */}
      <h3>子组件2 --- {props.message}</h3>
    </div>
  )
}

4. 跨代组件通信:Context 传送门

如果组件层级很深,比如"爷爷 -> 爸爸 -> 儿子 -> 孙子",如果还用 Props 一层层传,那中间的爸爸和儿子就成了无辜的"搬运工",代码会变得非常臃肿麻烦。

为了解决这个问题,React 提供了一个 Context (上下文)机制。这就像在家族里设立了一个"广播站",爷爷在顶层广播,底下的任何一代子孙,只要想听,就可以直接接收信号,完全不需要中间人转手。
爷组件(数据源头):

我们需要先 createContext 创建一个信号塔,然后用 <Context.Provider> 把所有后代包起来,value 就是我们要广播的数据。

jsx 复制代码
import Parent from "./Parent"
import { createContext } from 'react'

export const Context = createContext()  // 1. 建立信号塔

export default function Grand() {

  return (
    <div>
      <h2> 爷组件 </h2>
      {/* 2. 发射信号,内容是 value 中的数据 */}
      <Context.Provider value= {'爷组件的数据'}>
        <Parent/>
      </Context.Provider>
    </div>
  )
}

父组件(路人甲):

你看,父组件完全不需要碰这些数据,它只需要安静地渲染它的子组件即可。

jsx 复制代码
import Child from "./Child"
export default function Parent() {

  return (
    <div>
      <h3>父组件</h3>
      <Child></Child>
    </div>
  )
}

孙子组件(数据接收者):

孙子组件不需要管它离爷爷隔了多少代,直接用 useContext 这个钩子函数,就能连上信号塔拿到数据。

jsx 复制代码
import { useContext } from 'react'
import { Context } from './Grand'  // 3. 引入信号塔定义

export default function Child() {
  // 4. 接收信号
  const msg = useContext(Context)

  return (
    <div>
      <h4>孙子组件 --- {msg}</h4>
    </div>
  )
}

结语

组件通信是 React 开发中最基本也最重要的内功。

  • 简单的父子关系,PropsCallback 是最轻量的选择;
  • 兄弟组件,记得找共同的父级帮忙周转;
  • 当层级太深感到繁琐时,Context 就是你的救星。

掌握了这四招,你就能从容应对绝大多数的组件交互场景,让数据在你的应用中流动得井井有条。

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax