【React】入门Day02 —— 表单控制、组件通信、副作用管理与自定义 Hook

        本文主要介绍了 React 的相关知识,包括表单控制、组件通信、副作用管理、自定义 Hook 以及 Hooks 使用规则等内容,并通过一些案例进行了说明,以下是详细总结:

1. React 表单控制

  • 受控绑定
    import React, { useState } from 'react';
    
    function App() {
      const [value, setValue] = useState('');
      return (
        <input 
          type="text" 
          value={value} 
          onChange={e => setValue(e.target.value)}
        />
      );
    }
    • 概念:使用 React 组件的状态(useState)控制表单的状态。
    • 示例代码:通过useState定义表单值状态,在input组件上绑定valueonChange事件,实现表单值与状态的同步。
  • 非受控绑定
    import React, { useRef } from 'react';
    
    function App() {
      const inputRef = useRef(null);
      const onChange = () => {
        console.log(inputRef.current.value);
      };
    
      return (
        <input 
          type="text" 
          ref={inputRef}
          onChange={onChange}
        />
      );
    }
    • 概念:通过获取 DOM 的方式获取表单的输入数据。
    • 示例代码:使用useRef创建引用,在input组件上绑定refonChange事件,通过引用获取表单值。

2. 案例 - B 站评论案例

  • 实现手机输入框评论内容并发布评论,涉及 id 处理(如使用uuid)和时间处理(如使用day.js)。
import React, { useState } from 'react';
import uuid from 'uuid';
import dayjs from 'dayjs';

function CommentComponent() {
  const [comment, setComment] = useState('');
  const handleSubmit = () => {
    const commentId = uuid.v4();
    const commentTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
    // 这里可以添加发送评论的逻辑,比如调用接口
    console.log(`评论内容:${comment},评论ID:${commentId},评论时间:${commentTime}`);
  };

  return (
    <div>
      <input 
        type="text" 
        value={comment} 
        onChange={e => setComment(e.target.value)}
      />
      <button onClick={handleSubmit}>发布评论</button>
    </div>
  );
}

3. React 组件通信

  • 概念:组件之间的数据传递,根据组件嵌套关系不同有不同通信手段。
  • 父子通信 - 父传子
    • 基础实现
      • 实现步骤:父组件在子组件标签上绑定属性传递数据,子组件通过props接收数据。
      • 示例代码:展示了父组件传递name属性给子组件,子组件接收并渲染的代码。
        function Son(props) {
          return <div>{props.name}</div>;
        }
        
        function App() {
          const name = 'this is app name';
          return (
            <div>
               <Son name={name}/>
            </div>
          );
        }
    • props 说明
      • 可以传递任意合法数据,如数字、字符串等多种类型。
      • props是只读对象,子组件只能读取不能直接修改,父组件数据由父组件修改。
    • 特殊的 prop - children:当内容嵌套在组件标签内部时,组件会在children属性中接收该内容。
  • 父子通信 - 子传父
    • 核心思路:子组件调用父组件传递的函数并传递参数。
    • 示例代码:子组件通过按钮点击事件调用父组件传递的函数,将数据传递给父组件。
      function Son({ onGetMsg }) {
        const sonMsg = 'this is son msg';
        return (
          <div>
            {/* 在子组件中执行父组件传递过来的函数 */}
            <button onClick={() => onGetMsg(sonMsg)}>send</button>
          </div>
        );
      }
      
      function App() {
        const getMsg = (msg) => console.log(msg);
      
        return (
          <div>
            {/* 传递父组件中的函数到子组件 */}
             <Son onGetMsg={getMsg}/>
          </div>
        );
      }
  • 兄弟组件通信
    • 实现思路:借助 “状态提升” 机制,通过共同的父组件进行数据传递,即 A 组件先子传父给父组件 App,App 再父传子给 B 组件。
    • 示例代码:展示了 A 组件传递数据给 App,App 再传递给 B 组件的完整代码。
      import { useState } from "react";
      
      function A({ onGetAName }) {
        // Son组件中的数据
        const name = 'this is A name';
        return (
          <div>
            this is A compnent,
            <button onClick={() => onGetAName(name)}>send</button>
          </div>
        );
      }
      
      function B({ name }) {
        return (
          <div>
            this is B compnent,
            {name}
          </div>
        );
      }
      
      function App() {
        const [name, setName] = useState('');
        const getAName = (name) => {
          setName(name);
        };
        return (
          <div>
            this is App
            <A onGetAName={getAName} />
            <B name={name} />
          </div>
        );
      }
      export default App;
  • 跨层组件通信
    • 实现步骤
      • 使用createContext创建上下文对象Ctx
      • 顶层组件(App)通过Ctx.Provider提供数据。
      • 底层组件(B)通过useContext获取数据。
    • 示例代码:展示了从 App 到 A 再到 B 组件的跨层通信代码。
      import { createContext, useContext } from "react";
      
      // 1. createContext方法创建一个上下文对象
      const MsgContext = createContext();
      
      function A() {
        return (
          <div>
            this is A component
            <B />
          </div>
        );
      }
      
      function B() {
        // 3. 在底层组件 通过useContext钩子函数使用数据
        const msg = useContext(MsgContext);
        return (
          <div>
            this is B compnent,{msg}
          </div>
        );
      }
      
      function App() {
        const msg = 'this is app msg';
        return (
          <div>
            {/* 2. 在顶层组件 通过Provider组件提供数据 */}
            <MsgContext.Provider value={msg}>
              this is App
              <A />
            </MsgContext.Provider>
          </div>
        );
      }
      export default App;

4. React 副作用管理 - useEffect

  • 概念理解:用于在 React 组件中创建由渲染本身引起的操作(副作用),如发送 AJAX 请求、更改 DOM 等。
    import React, { useEffect, useState } from 'react';
    
    function App() {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        // 这里可以模拟发送请求获取数据
        const mockData = { message: '模拟数据' };
        setData(mockData);
      }, []);
    
      return (
        <div>
          {data && <div>{data.message}</div>}
        </div>
      );
    }
    基础使用
    • 需求示例:在组件渲染完毕后从服务端获取频道列表数据并显示。
      import React, { useEffect, useState } from 'react';
      
      function App() {
        const [data, setData] = useState(null);
      
        useEffect(() => {
          fetch('https://example.com/api/data')
          .then(response => response.json())
          .then(data => setData(data));
        }, []);
      
        return (
          <div>
            {data && <div>{data.message}</div>}
          </div>
        );
      }
    • 参数说明
      • 参数 1 是副作用函数,内部放置要执行的操作。
      • 参数 2 是可选的数组(依赖项),影响副作用函数的执行时机,空数组时只在初始渲染后执行一次。
  • useEffect 依赖说明
    • 无依赖项时,组件初始渲染和更新时执行副作用函数。
    • 空数组依赖时,只在初始渲染时执行一次。
    • 添加特定依赖项时,组件初始渲染和依赖项变化时执行。
  • 清除副作用
    • 概念:清理在useEffect中编写的对接组件外部的操作,如组件卸载时清理定时器。
    • 示例代码:展示了在useEffect中开启定时器,并在组件卸载时清理定时器的代码。
      import React, { useEffect, useState } from 'react';
      
      function Son() {
        // 1. 渲染时开启一个定时器
        useEffect(() => {
          const timer = setInterval(() => {
            console.log('定时器执行中...');
          }, 1000);
          return () => {
            // 清除副作用(组件卸载时)
            clearInterval(timer);
          }
        }, []);
        return <div>this is son</div>;
      }
      
      function App() {
        // 通过条件渲染模拟组件卸载
        const [show, setShow] = useState(true);
        return (
          <div>
            {show && <Son />}
            <button onClick={() => setShow(false)}>卸载Son组件</button>
          </div>
        );
      }
      export default App;

5. 自定义 Hook 实现

  • 概念:以use打头的函数,用于实现逻辑的封装和复用。
  • 示例代码:展示了一个自定义useToggle函数,封装了布尔值切换的逻辑,并在其他组件中使用的代码,同时介绍了自定义 hook 的通用封装思路。
    import { useState } from 'react';
    
    function useToggle() {
      // 可复用的逻辑代码
      const [value, setValue] = useState(true);
      const toggle = () => setValue(!value);
      // 哪些状态和回调函数需要在其他组件中使用 return
      return {
        value,
        toggle
      };
    }
    
    function App() {
      const { value, toggle } = useToggle();
      return (
        <div>
          {value && <div>this is div</div>}
          <button onClick={toggle}>toggle</button>
        </div>
      );
    }

6. React Hooks 使用规则

  • 只能在组件中或其他自定义 Hook 函数中调用。
  • 只能在组件的顶层调用,不能嵌套在iffor或其他函数中。

7. 案例 - 优化 B 站评论案例

import React, { useState } from 'react';
import { useEffect } from 'react-hooks';

// 自定义Hook函数封装数据请求逻辑
function useFetchComments() {
  const [comments, setComments] = useState([]);
  useEffect(() => {
    fetch('https://example.com/api/comments')
    .then(response => response.json())
    .then(data => setComments(data));
  }, []);
  return comments;
}

function CommentItem({ comment }) {
  return <div>{comment.text}</div>;
}

function CommentList() {
  const comments = useFetchComments();
  return (
    <div>
      {comments.map(comment => (
        <CommentItem key={comment.id} comment={comment} />
      ))}
    </div>
  );
}

function App() {
  return (
    <div>
      <CommentList />
    </div>
  );
}
  • 使用请求接口的方式获取评论列表并渲染。
  • 使用自定义 Hook 函数封装数据请求的逻辑。
  • 把评论中的每一项抽象成一个独立的组件实现渲染。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886034.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WebRTC入门

主要参考资料&#xff1a; WebRTC 在 ESP32 系列硬件平台上的实现: https://www.bilibili.com/video/BV1AEHseWEda/?spm_id_from333.337.search-card.all.click&vd_sourcedd284033cd0c4d1f3f59a2cd40ae4ef9 火山 RTC豆包大模型&#xff0c;给用户体验装上银色子弹: https:…

【网络安全】Cookie与ID未强绑定导致账户接管

未经许可,不得转载。 文章目录 前言正文前言 DigiLocker 是一项在线服务,旨在为公民提供一个安全的数字平台,用于存储和访问重要的文档,如 Aadhaar 卡、PAN 卡和成绩单等。DigiLocker 通过多因素身份验证(MFA)来保护用户账户安全,通常包括 6 位数的安全 PIN 和一次性密…

【RabbitMQ】面试题

在本篇文章中&#xff0c;主要是介绍RabbitMQ一些常见的面试题。对于前几篇文章的代码&#xff0c;都已经在码云中给出&#xff0c;链接是mq-test: 学习RabbitMQ的一些简单案例 (gitee.com)&#xff0c;如果存在问题的话欢迎各位提出&#xff0c;望共同进步。 MQ的作用以及应用…

sentinel原理源码分析系列(一)-总述

背景 微服务是目前java主流开发架构&#xff0c;微服务架构技术栈有&#xff0c;服务注册中心&#xff0c;网关&#xff0c;熔断限流&#xff0c;服务同学&#xff0c;配置中心等组件&#xff0c;其中&#xff0c;熔断限流主要3个功能特性&#xff0c;限流&#xff0c;熔断&…

《OpenCV》—— 指纹验证

用两张指纹图片中的其中一张对其验证 完整代码 import cv2def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)def verification(src, model):sift cv2.SIFT_create()kp1, des1 sift.detectAndCompute(src, None)kp2, des2 sift.detectAndCompute(model, None)fl…

使用 Llama 3.1 和 Qdrant 构建多语言医疗保健聊天机器人的步骤

长话短说&#xff1a; 准备好深入研究&#xff1a; 矢量存储的复杂性以及如何利用 Qdrant 进行高效数据摄取。掌握 Qdrant 中的集合管理以获得最佳性能。释放上下文感知响应的相似性搜索的潜力。精心设计复杂的 LangChain 工作流程以增强聊天机器人的功能。将革命性的 Llama …

在线代码编辑器

在线代码编辑器 文章说明前台核心代码后台核心代码效果展示源码下载 文章说明 采用Java结合vue3设计实现的在线代码编辑功能&#xff0c;支持在线编辑代码、运行代码&#xff0c;同时支持导入文件&#xff0c;支持图片识别&#xff0c;支持复制代码&#xff0c;可将代码导出为图…

《RabbitMQ篇》基本概念介绍

MQ功能 解耦 MQ允许不同系统或组件之间松散耦合。发送者和接收者不需要直接连接&#xff0c;从而提高了系统的灵活性和可维护性。异步处理 使用MQ可以实现异步消息传递&#xff0c;发送者可以将消息放入队列后立即返回&#xff0c;不必等待接收者处理。这提高了系统的响应速度…

Kafka学习笔记(一)Kafka基准测试、幂等性和事务、Java编程操作Kafka

文章目录 前言4 Kafka基准测试4.1 基于1个分区1个副本的基准测试4.2 基于3个分区1个副本的基准测试4.3 基于1个分区3个副本的基准测试 5 Java编程操作Kafka5.1 引入依赖5.2 向Kafka发送消息5.3 从Kafka消费消息5.4 异步使用带有回调函数的生产消息 6 幂等性6.1 幂等性介绍6.2 K…

【BurpSuite】SQL注入 | SQL injection(1-2)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】SQL注入 | SQL injection&#xff08;1-2&#xff09; 实验一 Lab: SQL injection vulnerability in WHERE clause…

基于微信的乐室预约小程序+ssm(lw+演示+源码+运行)

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

字体文件压缩

技术点 npm、html、font-spider 实现原理 个人理解&#xff1a;先引入原先字体&#xff0c;然后重置字符为空&#xff0c;根据你自己填充文字、字符等重新生成字体文件&#xff0c;因此在引入的时候务必添加自己使用的文字、字符等&#xff01;&#xff01;&#xff01; 实…

TDengine 流计算与窗口机制的深度解析:揭示计数窗口的关键作用

在 TDengine 3.2.3.0 版本中&#xff0c;我们针对流式计算新增了计数窗口&#xff0c;进一步优化了流式数据处理的能力。本文将为大家解读流式计算与几大窗口的关系&#xff0c;并针对新增的计数窗口进行详细的介绍&#xff0c;帮助大家进一步了解 TDengine 流式计算&#xff0…

解决MySQL报Incorrect datetime value错误

目录 一、前言二、问题分析三、解决方法 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导&#xff0c;有什么不对的地方&#xff0c;我会及时改进哦~ 博客主页链接点这里–>&#xff1a;权权的博客主页链接 二、问题分析 这个错误通常出现在尝试将一个不…

沂机管理系统/data/Ajax.aspx接口存在SQL注入漏洞

漏洞描述 沂机管理系统/data/Ajax.aspx接口存在SQL注入漏洞&#xff0c;攻击者可以获取服务器权限 漏洞复现 body"后台管理系统演示版" POC GET /data/Ajax.aspx?methodlog_list&page1&limit20&fkey1&fdate12024-10-0100%3A00%3A00&fdate2…

Postgresql源码(136)syscache/relcache 缓存及失效机制

相关 《Postgresql源码&#xff08;45&#xff09;SysCache内存结构与搜索流程分析》 0 总结速查 syscache&#xff1a;缓存系统表的行。通用数据结构&#xff0c;可以缓存一切数据&#xff08;hash dlist&#xff09;。可以分别缓存单行和多行查询。 syscache使用CatCache数…

AI 对话工具汇总

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏AI_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 前言: 正文: 前言: 在科技飞速发展的时代&#xff0c;AI 对话正逐渐成为我们获取信息、交流思想的新方式。它以强…

算法笔记(四)——模拟

算法笔记&#xff08;四&#xff09;——模拟 文章目录 算法笔记&#xff08;四&#xff09;——模拟替换所有的问号提莫攻击Z字形变换外观数列数青蛙 模拟算法就是根据题目的要求&#xff0c;题目让干神马就做神马&#xff0c;一步一步来 替换所有的问号 题目&#xff1a;替换…

初识TCP/IP协议

回顾上文 来回顾一下TCP协议的特性&#xff0c;有一道比较经典的题&#xff1a;如何使用UDP实现可靠传输&#xff0c;通过应用程序的代码&#xff0c;完成可靠传输的过程&#xff1f; 原则&#xff0c;TCO有啥就吹啥&#xff0c;引入滑动窗口&#xff0c;引入流量控制&#x…

【RabbitMQ——具体使用场景】

1. 异步 1.1 同步异步的问题&#xff08;串行&#xff09; 串行方式&#xff1a;将订单信息写入数据库成功后&#xff0c;发送注册邮件&#xff0c;再发送注册短信。以上三个任务全部完成后&#xff0c;返回给客户端 public void makeOrder(){// 1 :保存订单 orderService.…