探讨:围绕 props 阐述 React 通信

在 ++✓ 🇨🇳 开篇:通过 state 阐述 React 渲染++ 中,以 setInterval 为例,梳理了 React 渲染的相关内容。

📢 本篇会 ++✓ 🇨🇳 围绕 props 阐述 React 通信++

props

React 组件使用 props 来互相通信。每个父组件都可以提供 props 给它的子组件,从而将一些信息传递给它。

html 复制代码
<Avatar
  name="ligang" 
  address={<span>山东省</span>}
  size={100}
/>

也可以拆分组件,将子组件作为 JSX 传递。

将 JSX 作为子组件传递
html 复制代码
<Avatar
  name="ligang" 
  size={100}>
  <span>山东省</span>
</Avatar>

上述 Avatar 组件将接收一个被设为 <span>children prop 。

javascript 复制代码
function Card({ children }) {
  return (
    <>{children}</>
  );
}

注意! 需要区分 childrenChildren

‼️ 在 React 中,children 属性是被视为 不透明的 数据结构。这意味着你不应该依赖它的结构。如果要转换,过滤,或者统计子节点,你应该使用 Children 方法。

实际操作过程中,children 在底层常常被表示为数组。但是如果这里只有一个子节点,那么 React 将不会创建数组,因为这将导致不必要的内存开销。 只要你使用 Children 方法而不是直接操作 children 底层结构,即使 React 改变了 children 数据结构的实际实现方式,你的代码也不会被中断。

语法 含义
Children.count(children) 可以获取 children 中的节点数量
Children.forEach(children, (child, index) => {}); 为每个 children 中的每个子节点执行一段代码
Children.map(children, child => {}, thisArg?) children 中的每个子节点进行映射或转换
Children.only(children) 断言 children 代表一个 React 元素
Children.toArray(children) 通过 children 创建一个数组

☔️ Children 使得错误排查变得较为困难,推荐使用 替代方案[1](#1) 而不是使用 Children

组件是否由 props 驱动,可以分为受控&非受控组件。

受控&非受控

当组件中的重要信息是由 props 而不是其自身状态驱动时,就可以认为该组件是 "受控组件" ;受控组件具有最大的灵活性,但它们需要父组件使用 props 对其进行配置。

javascript 复制代码
export default function Input ({value, onChange}) {
  return (
  	<input 
    	value={value} 
			onChange={e => {onChange(e.target.value)}}
    />
  )
}

当组件中的重要信息是由其自身状态 state驱动时,就可以认为该组件是 "非受控组件";非受控组件通常很简单,因为它们不需要太多配置。

javascript 复制代码
export default function Input () {
  const [value, setValue] = useState('');
  return (
  	<input
     value={value}
		 onChange={e => {setValue(e.target.value)}}
    />  
  )
}

♠︎♠︎ 当编写一个组件时,你应该考虑哪些信息应该受控制(通过 props),哪些信息不应该受控制(通过 state)。

业务开发中,组件是受控或者非受控是明确的。但组件库中(如antd)有非常多的场景需要既支持受控模式又支持非受控模块(如input) <= 组件的状态既可以自己管理,也可以被外部控制。

推荐查看 ahooks useControllableValue[2](#2)

‼️区分:纯函数
  • 只负责自己的任务。它不会更改在该函数调用前就已存在的对象或变量。
  • 输入相同,则输出相同。给定相同的输入,纯函数应总是返回相同的结果。

不更改在该函数调用前就已存在的对象或变量 => 对于 props 同样至关重要!

将 props 视为只读

🧶 探讨:不要在 state 中镜像 props

父组件

javascript 复制代码
import {useState} from 'react';
import Message from './Message.tsx';

export default function Hello () {
    const [message, setMessage] = useState('world');
    return (
        <>
            <input type="text" value={message} onChange={(e) => setMessage(e.target.value)}/>
            <Message message={message}></Message>
        </>
    )
}

子组件

javascript 复制代码
import {useState} from 'react';

export default ({message}: {message: string}) => {
    const [msg, setMsg] = useState(message);
    return <div>hello {msg}</div>
}

‼️这里,一个 msg state 变量被初始化为 message 的 prop 值。这段代码的问题在于,如果父组件稍后传递不同的 message 值(例如,将其从 'world' 更改为 'ligang'),则 msg state 变量将不会更新! state 仅在第一次渲染期间初始化。

这就是为什么在 state 变量中,"镜像"一些 prop 属性会导致混淆的原因。相反,你要在代码中直接使用 message 属性。

💯 如果你想给它起一个更短的名称,请使用常量:

javascript 复制代码
export default ({message}: {message: string}) => {
    const msg = message;

这种写法就不会与从父组件传递的属性失去同步。

🔛只有当你 想要 忽略特定 props 属性的所有更新时,将 props "镜像"到 state 才有意义。

按照惯例,prop 名称以 initialdefault 开头,以阐明该 prop 的新值将被忽略:

javascript 复制代码
export default ({initialMessage}: {initialMessage: string}) => {
    // 这个 `message` state 变量用于保存 `initialMessage` 的 **初始值**。
  	// 对于 `initialMessage` 属性的进一步更改将被忽略。
  	const [msg, setMsg] = useState(initialMessage);

  1. https://react.docschina.org/reference/react/Children#alternatives Children替代方案 ↩︎

  2. https://ahooks.js.org/zh-CN/hooks/use-controllable-value#usecontrollablevalue usecontrollablevalue ↩︎

相关推荐
LaughingZhu5 小时前
智能体经典范式构建:ReAct、Plan-and-Solve 与 Reflection
前端·react.js·前端框架
飞天狗6 小时前
长列表滚动卡顿怎么破:虚拟列表选型 + react-virtuoso 实战调优指南
react.js·性能优化
binbin_529 小时前
React 井字棋教程:用一个小游戏理解组件和状态
前端·react.js·前端框架
张元清10 小时前
React useObjectUrl Hook:预览文件与 Blob,不留内存泄漏(2026)
javascript·react.js
真的想不出名儿13 小时前
Md编辑器整合-react
前端·react.js·编辑器
牛仔只喝牛奶1 天前
多端跨端技术选型:小程序 + H5 + App 的两栈拆分落地
react native·react.js
wear工程师1 天前
setState 到底是不是异步的?这题从 React 16 问到 18,标准答案早就变了
react.js·面试
wanghowie1 天前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
csj501 天前
前端基础之《React(11)—state声明式》
前端·react.js
张元清1 天前
React useLocalStorage Hook:SSR 安全的持久化状态(2026)
javascript·react.js