前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探讨:围绕 props 阐述 React 通信

探讨:围绕 props 阐述 React 通信

作者头像
奋飛
发布2024-05-25 19:19:47
810
发布2024-05-25 19:19:47
举报
文章被收录于专栏:Super 前端

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

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

props

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

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

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

将 JSX 作为子组件传递
代码语言:javascript
复制
<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 而不是使用 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 useControllableValue2

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

不更改在该函数调用前就已存在的对象或变量 => 对于 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 ↩︎
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • props
    • 将 JSX 作为子组件传递
    • 受控&非受控
      • ‼️区分:纯函数
      • 将 props 视为只读
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档