• 探讨:围绕 props 阐述 React 通信


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

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

    props

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

    <Avatar
      name="ligang" 
      address={>山东省span>}
      size={100}
    />
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    将 JSX 作为子组件传递
    <Avatar
      name="ligang" 
      size={100}>
      <span>山东省span>
    Avatar>
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    function Card({ children }) {
      return (
        <>{children}</>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意! 需要区分 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 对其进行配置。

    export default function Input ({value, onChange}) {
      return (
      	<input 
        	value={value} 
    			onChange={e => {onChange(e.target.value)}}
        />
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    export default function Input () {
      const [value, setValue] = useState('');
      return (
      	<input
         value={value}
    		 onChange={e => {setValue(e.target.value)}}
        />  
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

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

    推荐查看 ahooks useControllableValue2

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

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

    将 props 视为只读

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

    父组件

    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>
            </>
        )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    子组件

    import {useState} from 'react';
    
    export default ({message}: {message: string}) => {
        const [msg, setMsg] = useState(message);
        return <div>hello {msg}</div>
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

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

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

    export default ({message}: {message: string}) => {
        const msg = message;
    
    • 1
    • 2

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

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

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

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

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

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

  • 相关阅读:
    基于工业无线DTU的空气污染监测防治方案
    ubuntu18.04平台上基于xenomai3.2对Linux内核的实时化改造
    如何用FLStudio水果21中文版创作音乐?(官方基础教程中文版)
    【云原生】都在说云原生?到底什么是云原生?
    ZMQ之脱机可靠性--巨人模式
    摩托车头盔的逆向建模与设计
    适合linux的软件
    ERROR 6400 --- [ main] com.zaxxer.hikari.pool.HikariPool : root - Exception
    评分插件 jQuery Raty
    快速入手node.js
  • 原文地址:https://blog.csdn.net/ligang2585116/article/details/136354820