react(基础篇)

React由Meta公司研发,用于构建Web和原生交互界面的库。

React 官方中文文档

查看JSX

(一)React组件

  • 用户界面的一部分,通俗的来讲,最小的元素组成的单元,可以实现部分逻辑与功能

  • 房子的门就可以看成一个组件,由木板和木方组成,有一定功能和作用,多个组件组合就可以形成房子了。

  • 组件之间可以相互嵌套,重复使用

React组件

  • React中,组件就是一个首字母大写的函数,内部存放组件的逻辑和视图UI,使用组件只需将组件当成标签写即可

  • 组件也不能返回多个 JSX 标签,必须将它们包裹到一个共享的父级中,比如 <div>...</div> 或使用空的 <>...</> 包裹:

  • 组件只负责自己的任务。 它不会更改在该函数调用前就已存在的对象或变量。

  • 组件输入相同,则输出相同。 给定相同的输入,组件应该总是返回相同的 JSX。

function MyButton() {return(<button >点了我</button>);
}const App = () => {return <MyButton ></MyButton>;};

Hook(钩子函数)

hook是特殊的函数,搭配函数组件一起使用,使其功能更强大

hook使用规则

  • 只能在顶层调用Hooks,不要在循环、条件判断或者嵌套函数中调用。
  • 只能在React函数组件或自定义Hook中调用Hooks。

(二)useState

为组件设置state可以让组件拥有记忆,完成交互

特点

  • State 变量 用于保存渲染间的数据。

  • State setter 函数 更新变量并触发 React 再次渲染组件

  • 只能在组件或[自定义 Hook]的最顶层调用

快速入门

  1. 在文件顶部导入useState

    import { useState } from 'react';
    
  2. 创建一个useState

    const [index, setIndex] = useState(0);
    

    useState 的唯一参数是 state 变量的初始值

useState细节理解

  1. 状态更新是异步的

    React 会将多个状态更新合并,以提高性能。因此,状态更新不会立即生效,而是会在下一次渲染时生效。

  2. 批量更新

    在 React 的事件处理函数中,多个状态更新会被批量处理,只触发一次重新渲染。

useState更新原理

State通过setState更新,实际上State只是可读的,setState更新只是将原来的值替换掉,而并非修改原数据

  1. 更新State对象

    通过...对象展开符快速跟新对象

    const [user, setUser] = useState({ name: 'Alice', age: 25 });// 更新年龄
    const updateAge = () => {setUser(prev => ({ ...prev, age: 26 }));
    };
    
  2. 更新State数组

    注意:即使你拷贝了数组,你还是不能直接修改其内部的元素,因为数组拷贝是浅拷贝

    避免使用 (会改变原始数组)推荐使用 (会返回一个新数组)
    添加元素pushunshiftconcat[...arr] 展开语法
    删除元素popshiftsplicefilterslice
    替换元素splicearr[i] = ... 赋值map
    排序reversesort先将数组复制一份,再排序

受控表单

使用react组件状态控制表单

const App = () => {const [value, setValue] = useState('');return (<><inputvalue={value}onChange={(e)=>setValue(e.target.value)}type="text"/></>)
};

如何构建State

  1. 先根据react数据驱动视图的特点,页面哪些UI状态改变会导致界面改变,就给它定义个State控制界面更新
  2. 然后根据构建State原则对State进行优化

构建State的原则

状态提升

要从多个子组件收集数据,或让两个子组件相互通信,请改为在其父组件中声明共享 state。父组件可以通过 props 将该 state 传回给子组件。这使子组件彼此同步并与其父组件保持同步。

(三)props

React中使用props进行参数传递

//value=0进行默认赋值,当value=null就读取默认值0
function Square({value=0, onSquareClick}) {return (<button className="square" onClick={onSquareClick}>{value}</button>);
}export default function App(){return(<div className="board-row"><Square value="1" onSquareClick={() => handleClick(0)}/><Square value="2" onSquareClick={() => handleClick(1)}/><Square value="3" onSquareClick={() => handleClick(2)}/></div>);
}

children属性

props.children 是一个特殊的属性,用于传递组件包裹的子元素(子节点)

children 可以是以下任意类型:

  • 字符串:直接作为文本内容。
  • React 元素:如 <div>、自定义组件等。
  • 数组:多个子元素组成的数组。
  • 函数:通过函数模式实现动态渲染(即 Render Props 模式)。
  • 空值nullundefinedfalse(不会被渲染)。
<Child><h1>标题</h1><p>段落</p>
</Child>// Child 组件内部:
function Child(props) {return <div>{props.children}</div>; // 同时渲染标题和段落
}

(四)UseContext跨层传递参数

Context是一种跨组件层级传递数据的机制,适合全局数据(如用户信息、主题、语言等),区别于props逐层传递。

  • Provider:通过 <MyContext.Provider value={data}> 向子组件树传递数据。
  • Consumer:通过 useContext(MyContext) 直接获取最近一层 Provider 提供的数据。

示例

假设有 3 层组件:ParentChildGrandchild,需要将用户信息从 Parent 直接传递到 Grandchild,无需经过 Child 中转。

// UserContext.js
import { createContext } from 'react';export const UserContext = createContext({ name: '默认用户', age: 0 
});
// Parent.jsx
import { UserContext } from './UserContext';
import Child from './Child';const Parent = () => {const user = { name: "小明", age: 20 };return (<UserContext.Provider value={user}><div><h2>Parent 组件</h2><Child /> {/* 子组件不需要传递任何 props! */}</div></UserContext.Provider>);
};
// Child.jsx
import Grandchild from './Grandchild';const Child = () => {return (<div><h3>Child 组件</h3><Grandchild /> {/* 同样无需传递 props */}</div>);
};
// Grandchild.jsx
import { useContext } from 'react';
import { UserContext } from './UserContext';const Grandchild = () => {const user = useContext(UserContext); // 直接获取数据return (<div><h4>Grandchild 组件</h4><p>用户名:{user.name}</p><p>年龄:{user.age}</p></div>);
};

(五)UseReducer集中状态管理

useReducer – React 中文文档

const [state, dispatch] = useReducer(reducer, initialState)

useReducer类似useState管理组件状态,而UseReudcer集中状态管理,管理方式类似“告诉reducer函数用户进行了什么操作“

参数

  • initialState:初始化状态
  • reducer函数:负责集中管理更新状态(组件状态更新就是在这里面)

返回值

  • state:目前状态
  • dispatch函数:主要负责记录用户进行了什么操作并记录值,比如点击更新按钮、点击删除按钮等

如何将State状态迁移至Reducer中

用State进行状态管理的Todo清单

function TodoList() {const [todos, setTodos] = useState([]);const [input, setInput] = useState('');const addTodo = () => {setTodos([...todos, input]);setInput('');};return (<div><inputtype="text"value={input}onChange={(e) => setInput(e.target.value)}/><button onClick={addTodo}>Add Todo</button><ul>{todos.map((todo, index) => (<li key={index}>{todo}</li>))}</ul></div>);
}

用Reducer进行状态管理的Todo清单

const initialState = {todos: [],input: '',
};function reducer(state, action) {switch (action.type) {case 'updateInput':return { ...state, input: action.payload };case 'addTodo':return { ...state, todos: [...state.todos, state.input], input: '' };default:return state;}
}function TodoList() {const [state, dispatch] = useReducer(reducer, initialState);return (<div><inputtype="text"value={state.input}onChange={(e) => dispatch({ type: 'updateInput', payload: e.target.value })}/><button onClick={() => dispatch({ type: 'addTodo' })}>Add Todo</button><ul>{state.todos.map((todo, index) => (<li key={index}>{todo}</li>))}</ul></div>);
}

(六)性能提升

React.memo

用memo包裹的组件拥有记忆缓存,当props没有改变该组件不会重新渲染

React.memo(function MyComponent(props){},可选参数)

特点

  • props与上一次相同(是同一个),如果props是对象或者数组,重新创建一个相同的新的,React也会认为不同,所以通常useMemo、useCallback一起使用
  • useContext多层传参也会导致Memo包裹的组件重新渲染,所以一般在外层接收作为props传入

useMemo

useMemo(函数,依赖数组),useMemo组成通常是函数和依赖数组,可以在每次重新渲染缓存计算结果(函数的返回值)

  • 函数是任意不带参的函数(一般用箭头函数),可返回任意值

  • 依赖数组:一般是props或useState

const TodoList=useMemo(()=>todo(tab,list),[tab,list])

useCallback

useCallback用来缓存函数,当依赖数组不发生改变时,函数不变,效果类似useMemo

useCallback(fn,dependencies)

区别useMemo和useCallback

区别useMemouseCallback
主要用途用于记忆计算结果用于记忆定义函数
返回值返回计算结果返回记忆函数
使用场景避免昂贵的计算避免不必要的子组件重新渲染

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构-哈希表(一)哈希函数、哈希表介绍、优缺点

哈希表 哈希函数哈希表使用了哈希函数来完成key到地址的快速映射&#xff0c;所以在了解哈希表之前&#xff0c;需要先明白哈希函数的概念和特点。 哈希函数的定义 哈希函数 哈希函数是一种将任意长度输入的数据&#xff0c;转换成固定长度输出的算法哈希函数H可以表示为yH(x) …

Shader开发(一)什么是渲染

前言在现代游戏开发和计算机图形学领域&#xff0c;渲染技术是连接虚拟世界与视觉呈现的关键桥梁。无论你是刚接触图形编程的新手&#xff0c;还是希望深入理解渲染原理的开发者&#xff0c;掌握渲染的核心概念都是必不可少的第一步。什么是渲染&#xff1f;渲染&#xff08;Re…

策略模式+工厂模式(案例实践易懂版)

最近,可以说这2025年度,自己更文的次数都大大减少,主要最近大环境不景气,自己职业也受到波及,学习的东西也是因为AI而变得更多, 没办法,你不学,总有人会学,关于AI的我也准备出个专辑,相信绝对帮助到大家 额,好像说多了,言归正传,我们看一下今天的主题:策略模式工厂模式 本文主要…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - snowNLP库实现中文情感分析

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解snowNLP库实现中文情感分析 视频在线地址&…

大根堆,小根堆,双指针

码蹄集OJ-大约 #include<bits/stdc.h> using namespace std; priority_queue<int>max2,maxDel; priority_queue<int,vector<int>,std::greater<int>>min2,minDel; const int N1e51; int n,result0,a[N]; int main( ) {cin>>n;for(int i1…

RS485和Modbus

UART协议中&#xff0c;空闲状态为高电平&#xff0c;也就是1,R25和R27&#xff0c;485收发器特性MAX485 (美信)SSP485 (国产替代)AZRS3080 (安格)供电电压5V5V3.3V ~ 5.5V静态电流300μA (接收模式)120μA (接收模式)150μA (接收模式)传输速率2.5Mbps10Mbps20Mbps总线负载能力…

【Android】交叉编译faiss库 | 问题解决

目录 一 解决 FAISS 交叉编译到 Android 时的 BLAS/MKL 依赖问题 二 交叉编译faiss ■禁用 BLAS并交叉编译faiss ■使用 OpenBLAS 的 Android 移植版本并交叉编译faiss 三 报错处理 ■报错 ■SWIG 一 解决 FAISS 交叉编译到 Android 时的 BLAS/MKL 依赖问题

《使用 IDEA 部署 Docker 应用指南》

使用 IDEA 部署 Docker 应用的详细步骤 一、创建 Dockerfile 配置文件 在项目根目录下创建Dockerfile文件&#xff0c;配置内容如下&#xff1a; # 使用官方的OpenJDK镜像作为基础镜像 FROM openjdk:17-jdk-slim# 设置维护者信息(可选) LABEL maintainer"三木豪"# 设…

【Docker#3】Window 和 Linux 上 docker安装 相关知识

前置了解&#xff1a; X86 高并发&#xff1a;基于 x86 架构的处理器&#xff0c;在高负载下处理大量并发请求的能力。ARM &#xff1a;使用 ARM 架构处理器的移动设备&#xff0c;具有低功耗和高性能的特点。 操作系统&#xff1a; CentOS&#xff1a;基于 Red Hat Enterprise…

一次 POI 版本升级踩坑记录

前言 结论先行。 开发过程中由于可能涉及到二次开发&#xff0c;若原系统开发时间久远&#xff0c;没有达成一致规范设计&#xff0c;导致风格各异&#xff0c;确实满足当时开发场景&#xff0c;但增大了后续的更新的难度&#xff0c;容易出现俄罗斯套娃现象&#xff0c;新的更…

硬件设计学习DAY13——电源缓冲电路设计全解

每日更新教程&#xff0c;评论区答疑解惑&#xff0c;小白也能变大神&#xff01;" 目录 一.缓冲电路介绍 1.1缓冲电路的作用 1.2寄生参数的来源 1.3缓冲电路的类型 1.4常见缓冲电路设计 1.5设计原则 二.吸收与缓冲 2.1吸收与缓冲的核心作用 2.2电压尖峰与吸收措…

鸿蒙搜狐新闻如何在Native调用ArkTS方法

01前言鸿蒙作为一款新兴的智能操作系统&#xff0c;现在适配鸿蒙系统的应用越来越多&#xff0c;同时会面临三端兼容问题&#xff0c;如同一产品功能&#xff0c;需要维护iOS、Android、鸿蒙三端代码。拿文件上传、下载功能场景举例&#xff0c;同时要适配iOS、Android、鸿蒙三…

Java行为型模式---中介者模式

中介者模式基础概念中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;其核心思想是通过一个中介对象来封装一系列对象之间的交互&#xff0c;使各对象不需要显式地相互引用&#xff0c;从而降低耦合度&#xff0c;并可以独立地改变它们之间…

Python爬虫实战:研究Korean库相关技术

一、引言 1.1 研究背景与意义 随着韩流文化在全球的传播,韩语网页内容急剧增加。韩国在科技、娱乐等领域的信息具有重要研究价值。然而,韩语独特的黏着语特性(如助词体系、词尾变化)给信息处理带来挑战。传统爬虫缺乏对韩语语言特点的针对性处理,本研究旨在开发一套完整…

表单校验--数组各项独立校验

写需求时遇到一个这样的问题&#xff0c;就是校样项是多个的&#xff0c;但是其字段名称相同这时我们可以这样校验&#xff0c;注意字段之间的关联性<div v-for"(item,index) in formData.hospitalDoctorList" :key"item.key || index"><el-form-…

基于SpringBoot和leaflet-timeline-slider的历史叙事GIS展示-以哪吒2的海外国家上映安排为例

目录 前言 一、哪吒2的海外之路 1、海外征战历程 2、上映国家空间查询 二、后端接口的实现 1、模型层的实现 2、上映时间与国家 3、控制层的实现 三、基于leaflet-timeline-slider的前端实现 1、时间轴控件的引入及定义 2、时间轴绑定事件 3、成果展示 四、总结 前言…

tar 解压:Cannot change ownership to uid 1000, gid 1000: Operation not permitted

tar 解压 tar.gz 压缩包报错&#xff1a; # tar xzf $INPUT_FOLDER/archive.tar.gz -C /mnt/test-nas/[..] tar: xx.jpg: Cannot change ownership to uid 1000, gid 1000: Operation not permitted原因是用普通用户执行的解压缩脚本&#xff0c;用root用户执行tar解压缩&…

腾讯客户端开发面试真题分析

以下是针对腾讯客户端开发工程师面试问题的分类与高频问题分析&#xff08;基于​​105道问题&#xff0c;总出现次数118次​​&#xff09;。按技术领域整合为​​7大类别​​&#xff0c;按占比排序并精选高频问题标注优先级&#xff08;1-5&#x1f31f;&#xff09;&#x…

线上问题排查之【CPU飙高100%】

目录 案例 发现问题 排查问题 步骤一 步骤二 步骤三 案例 import java.util.concurrent.TimeUnit;/*** 简单写一个CPU飙高的案例*/ public class CpuLoadUp {// 这里定义了一个标识private volatile static int flag 0;public static void main(String[] args) {// 执行…

c语言 进阶 动态内存管理

动态内存管理1. 为什么存在动态内存分配2. 动态内存函数的介绍​2.1 malloc 和 freemalloc 函数free 函数2.2内存泄漏2.3 calloc2.4 realloc3. 常见的动态内存错误3.1 对NULL指针的解引用操作3.2 对动态开辟空间的越界访问3.3 对非动态开辟内存使用free释放3.4 使用free释放一块…