当前位置: 首页 > news >正文

《2023 年 React 生态》

大家好,我是 Chocolate。

前不久看到一篇不错的内容,来自于 The React Ecosystem in 2023,也结合自己今年使用的 React 生态总结一下。

本文并非视频演讲稿,和视频内容还是有一点点区别,视频内容相对来说会更加详细一点,这里放一下视频传送门:

b 站: https://www.bilibili.com/video/BV1Zh4y1G78R/
youtube: https://www.youtube.com/watch?v=VvSIM1XKuIA

选择你喜欢的平台即可,如果可以的话留下你的点赞和关注就是对我更新最大的鼓励!

前言

React 不知不觉到 23 年已经有 10 年之久了,下面是来自于网图,关于 10 周年的生日蛋糕:

关于这个生态方面,也有挺多内容,去年下半年到今年上半年,这一年时间,我也逐渐接触了一些新的工具,有些非常好用,就是那种一旦使用了,在任何项目中都必须要安装了,不用就顺手,那我们就快速进入正文吧:

开始使用

我记得我在接触前端的时候,那会还在大三阶段,还只是懵懂的学了一些 html 和 js,css 都没怎么用,说实在一点,还只是使用 java + jsp 实现一些非常简单的逻辑,可是那会还是觉得很有成就感,能自己做点表单页面出来。

再到之后大三课程设计了解到了 Vue 和 React 框架,最开始其实还是接触 Vue,不过还是 Vue2 的时代。

后来因为工作需要,开始接触了 react,接触了 hooks 语法之后,感觉就很棒,可惜 Vue3 慢了那么一点点,当时还不够稳定,但现阶段 Vue 也挺香的,跟着 antfu 大佬学就是了,很多工具也是从他那里了解的。

环境问题

过去学编程总是会遇到环境问题,学生时代主要是 windows 电脑,有时候找到了不对的教程, npm run 一跑就报错,但是正因为解决了这些问题,能力也不断提升了。

现在我们也可以使用一些云端 IDE,比如 CodeSandbox 与 StackBlitz,国内的话比如 cloudstudio 等,对于初学者来说可以直接跟随文档教程去写代码了,而无需考虑环境问题,有时候就是环境老是报错,一下就劝退了。

现如今的一些官方文档也比以前好了不少,提供在线 demo,不会的跟着教程手写一遍完全就可以上手了,非常方便。

当然,等你熟悉了语法以后,最好还是自己能配置一下项目,从零搭建起来,提升动手能力。

借助工具

在过去其实一般都是以 CRA(Create React App)为主,现在(23 年 6 月中旬)看这个仓库是有 100k star 了。

但是呢, cra 这玩意也讨论了挺久,关键还是修改 webpack 配置问题,不过社区里面也有解决方案:

CRACO - Create React App Configuration Override, an easy and comprehensible configuration layer for create-react-app.

其次,就是使用 Vite,提升开发体验!地址在这:Vite Getting Started

pnpm create vite

不过,自从我开始接触了 Next.js 之后,就用着那一套了,也很方便自己做全栈方面。

可以使用如下脚手架工具去配置一个 Next.js 项目:

npx create-next-app@latest

当然,这个配置出来的只是很简单的项目,许多配置还需要开发人员自己去弄,我在学的时候是用的这个模版:

🔋 Next.js + Tailwind CSS + TypeScript starter and boilerplate packed with useful development features

下文我也会提到这里面具体的一些技术栈。

不过,现阶段我更喜欢用 t3-app(The best way to start a full-stack, typesafe Next.js app)

非常好用!

路由

提到路由,一般会想到 React Router,下面是 6.8 版本简单示例代码:

import { Routes, Route, Outlet, Link } from "react-router-dom";export default function App() {return (<div><h1>Basic Example</h1><p>This example demonstrates some of the core features of React Routerincluding nested <code>&lt;Route&gt;</code>s,{" "}<code>&lt;Outlet&gt;</code>s, <code>&lt;Link&gt;</code>s, and using a"*" route (aka "splat route") to render a "not found" page when someonevisits an unrecognized URL.</p>{/* Routes nest inside one another. Nested route paths build uponparent route paths, and nested route elements render insideparent route elements. See the note about <Outlet> below. */}<Routes><Route path="/" element={<Layout />}><Route index element={<Home />} /><Route path="about" element={<About />} /><Route path="dashboard" element={<Dashboard />} />{/* Using path="*"" means "match anything", so this routeacts like a catch-all for URLs that we don't have explicitroutes for. */}<Route path="*" element={<NoMatch />} /></Route></Routes></div>);
}function Layout() {return (<div>{/* A "layout route" is a good place to put markup you want toshare across all the pages on your site, like navigation. */}<nav><ul><li><Link to="/">Home</Link></li><li><Link to="/about">About</Link></li><li><Link to="/dashboard">Dashboard</Link></li><li><Link to="/nothing-here">Nothing Here</Link></li></ul></nav><hr />{/* An <Outlet> renders whatever child route is currently active,so you can think about this <Outlet> as a placeholder forthe child routes we defined above. */}<Outlet /></div>);
}function Home() {return (<div><h2>Home</h2></div>);
}function About() {return (<div><h2>About</h2></div>);
}function Dashboard() {return (<div><h2>Dashboard</h2></div>);
}function NoMatch() {return (<div><h2>Nothing to see here!</h2><p><Link to="/">Go to the home page</Link></p></div>);
}

使用 React Router 的话需要自己去配置一遍,而我的话更喜欢文件路由的形式,所以我也就更喜欢直接使用 Next.js 的 Pages Router,新版的 App Router 依旧还是有点不习惯,需要嵌套使用。

关于路由的话还有一个 TanStack Router,TanStack 里还是有一些提升开发体验的工具库。

客户端状态管理

提到状态管理,你也许会想到 Redux,不过它还是存在一些问题的,比较推荐的是使用 Redux Toolkit,以下是简单的示例代码:

import { createSlice } from '@reduxjs/toolkit'const initialState = {value: 0,
}export const counterSlice = createSlice({name: 'counter',initialState,reducers: {increment: (state) => {state.value += 1},decrement: (state) => {state.value -= 1},incrementByAmount: (state, action) => {state.value += action.payload},},
})// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actionsexport default counterSlice.reducer

不过我除开工作上没办法,项目已经做成这样了,能不用也就不用,目前更喜欢使用 Zustand,以下是示例代码:

import { create } from 'zustand'type Store = {count: numberinc: () => void
}const useStore = create<Store>()((set) => ({count: 1,inc: () => set((state) => ({ count: state.count + 1 })),
}))function Counter() {const { count, inc } = useStore()return (<div><span>{count}</span><button onClick={inc}>one up</button></div>)
}

上述是使用了 ts 语法,可以看到,你完全可以像 hooks 一样去使用,而不需要一些模板代码,上手起来也很快速。

类似地还有一个 jotai,这个和我之前使用的 recoil 看起来语法挺像,都有 atom 的概念。

服务端状态管理

上文提到的 tanstack,里面就有一个 query,名字叫 tanstack query ,示例代码如下:

import {QueryClient,QueryClientProvider,useQuery,
} from '@tanstack/react-query'const queryClient = new QueryClient()export default function App() {return (<QueryClientProvider client={queryClient}><Example /></QueryClientProvider>)
}function Example() {const { isLoading, error, data } = useQuery({queryKey: ['repoData'],queryFn: () =>fetch('https://api.github.com/repos/tannerlinsley/react-query').then((res) => res.json(),),})if (isLoading) return 'Loading...'if (error) return 'An error has occurred: ' + error.messagereturn (<div><h1>{data.name}</h1><p>{data.description}</p><strong>👀 {data.subscribers_count}</strong>{' '}<strong>{data.stargazers_count}</strong>{' '}<strong>🍴 {data.forks_count}</strong></div>)
}

其实去年的时候,我就有了解过 SWR

“SWR” 这个名字来自于 stale-while-revalidate:一种由 HTTP RFC 5861(opens in a new tab) 推广的 HTTP 缓存失效策略。这种策略首先从缓存中返回数据(过期的),同时发送 fetch 请求(重新验证),最后得到最新数据。

也在项目中集成过,不过今后我应该会考虑用一用 tanstack query。

以及我在过去的视频也有提到过 GraphQL,不过在我了解了 tRPC 了之后,我又更喜欢使用 tRPC 带来的编程体验了。

Form

在过去使用 form,我其实都是使用组件库里面的,比如 antd 里面的,它确实也挺好用的,如果是要做后台的话直接用 antd pro 一把梭哈就完事了。

不过如果我们要单独使用 form 的话,react-hook-form 是我使用起来比较舒适的,社区里面还有一个 formik,可以了解一下,个人觉得 react-hook-form 够用了。

react-hook-form 的示例代码如下:

import { useForm, SubmitHandler } from "react-hook-form";type Inputs = {example: string,exampleRequired: string,
};export default function App() {const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>();const onSubmit: SubmitHandler<Inputs> = data => console.log(data);console.log(watch("example")) // watch input value by passing the name of itreturn (/* "handleSubmit" will validate your inputs before invoking "onSubmit" */<form onSubmit={handleSubmit(onSubmit)}>{/* register your input into the hook by invoking the "register" function */}<input defaultValue="test" {...register("example")} />{/* include validation with required or other standard HTML validation rules */}<input {...register("exampleRequired", { required: true })} />{/* errors will return when field validation fails  */}{errors.exampleRequired && <span>This field is required</span>}<input type="submit" /></form>);
}

测试

测试是构建高质量 React 应用程序的重要组成部分。在测试 React 应用程序时,需要考虑的两个很好的选择是用于单元测试的 Vitest 和 React 测试库,以及用于端到端测试的 Playwright 或 Cypress。

Vitest 在去年好像还上了一个榜单来着,当时没有记录,看来以后得多记录一些动态。

不过本人目前还没使用过,工作中需求进度比较赶,也没人集成这些,倒是见到开源社区里会有,工作中的话也有专门的人去写自动化测试,所以得看场景。

CSS

这一年内,我最喜欢的还是 tailwindcss,也正是有 tailwindcss 这个文档网站,也让我了解了一些 css 语法知识,原来有些效果属性可以这样那样使用。

在过去旧的项目,我看到挺多都是使用 Styled Components,还有的非常老的项目就直接行内样式一把梭哈,不过写着写着你会发现,原来写行内样式还越写越爽了, tailwindcss 使用体验还是挺棒的。

类似的还有 UnoCSS,也很棒,看个人选择。

而 Styled Components 的话我见的比较多的是 Emotion,也是 CSS-in-JS 的形式。

UI 库

日常使用我主要是以 antd 和 antd pro 为主,不过了解了 tailwindcss 后,shadcn/ui 也不错,配合 tailwindcss 还是挺香的。

动画

依旧还是以 react-spring 和 Framer Motion 为主。

不过我还了解有 GSAP,我在去年用的时候犹记得还没有对应 react 版本,在那次录制的时候发现是有的:

其它

因为有些是挺常见的,基本上一段时间也不怎么会改变的,比如国际化、数据可视化、类型安全方面,这些都是用的比较主流的库,而且是一直在持续维护和更新的。

文档的话,挺早就在关注着 Docusaurus,如今 2.0 版本已经比较稳定了:

以及 Next.js 团队做的文档工具 nextra,这个仓库在只有几百 star 的时候我就关注着的,因为之前 SWR 文档网站就是用这个构建的,之后貌似独立出来了出了文档工具:


也是因为这两个网站,让我了解到原来不只有 md,还有 MDX!

当然,要细说 React 肯定还有很多很多,比如 umi,dumi 以及其他一些非常好用的库。

这里就再提一点 Dev Tools,其实让我想到 Nuxt 之前出的 devtools 以及 studio,个人感觉很棒,对开发者来说真的太好了,这也是为什么我很喜欢 js 的一点吧。

之前倒是看到一些消息,貌似 Next.js 也在做 devtools 相关的事情,我感觉他们也应该要做,还是蛮期待的。

总结

很高兴能和各位分享自己所使用的 React 生态,以及通过那篇文章了解了大概的生态内容,本文也还有许多不足,比如也许了解的框架还不够,部分内容并未提及到,主要是以我当前水平视角去说,带有一些个人体验感受,可谓是美中不足吧。

相关文章:

《2023 年 React 生态》

大家好&#xff0c;我是 Chocolate。 前不久看到一篇不错的内容&#xff0c;来自于 The React Ecosystem in 2023&#xff0c;也结合自己今年使用的 React 生态总结一下。 本文并非视频演讲稿&#xff0c;和视频内容还是有一点点区别&#xff0c;视频内容相对来说会更加详细一…...

武职302303笔记-day01

这里写自定义目录标题 开发永和小票开发步骤1、对页面进行需求分析 使用CSS的方式 Order.html问题&#xff1a;html代码和css样式代码交织 idea开发后端程序使用chatGPT给我们打工QRCreate.java 开发永和小票 开发步骤 1、对页面进行需求分析 页面是很多文字组成&#xff0c;…...

Python面试高频100题【11~15题】

Python面试必知100例。收集整理了目前Python岗位常见的面试题&#xff0c;希望大家通过学习理解相关知识点。下面介绍的是11~15道题。 十一、请介绍下Python中单下划线与双下划线区别 在Python中&#xff0c;单下划线和双下划线主要用于命名变量和方法&#xff0c;而它们具有不…...

Linux下Redis 存储

命令使用 目录 命令使用 RDB持久化 AOF持久化 yum安装 [rootlocalhost ~]# yum -y install redis 已加载插件&#xff1a;fastestmirror Loading mirror speeds from cached hostfile* c7-media: * epel: ftp.yz.yamagata-u.ac.jpvim到文件etc/redis.conf 取消注释requirep…...

QML 快速上手3 - QuickControl2

目录 QuickControl2简介风格设置control 配置文件图像浏览器案例component 组件报错问题StackViewSwipeView QuickControl2 简介 quickcontrol 用于快速构建风格化的用户界面 它包括了以下几个预制的组件风格 Default QT 默认风格Universal windows 桌面风格Material 谷歌推…...

QT Creator写一个简单的电压电流显示器

前言 本文主要涉及上位机对接收的串口数据处理&#xff0c;LCD Number控件的使用。之前的一篇写一个简单的LED控制主要是串口发出数据&#xff0c;这里再看一下怎么接收数据处理数据&#xff0c;这样基本就对串口上位机有简单的认识了。 LCD Number显示时间 这一小节通过用一…...

前端需要的技能

语言&#xff1a; 1&#xff0c;熟练掌握html5&#xff0c;css3&#xff0c;javascript&#xff0c;ajax 2&#xff0c;掌握PHP、java、python中至少一种web开发语言 3&#xff0c;库/框架:MooTools,YUI,Angular,jQuery,Dojo. 4&#xff0c;UI框架&#xff1a;BootStrap,Founda…...

Qt——Qt控件之基于模型的项目视图组-QTreeView树形视图控件的使用总结(Qt仿word标题列表的实现)

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》...

spring boot框架步骤

目录 1. 创建一个新的Spring Boot项目2. 添加所需的依赖3. 编写应用程序代码4. 配置应用程序5. 运行应用程序6. 编写和运行测试7. 部署应用程序 总结 当使用Spring Boot框架开发应用程序时&#xff0c;以下是一些详细的步骤&#xff1a; 1. 创建一个新的Spring Boot项目 使用…...

动态创建select

1.动态创建select function createSelect(){ var mySelect document.createElement("select"); mySelect.id "mySelect"; document.body.appendChild(mySelect); } 2.添加选项option function addOption(){ //根据id查找对象&#xff0c; var objdoc…...

linux-centos7操作系统查看系统未挂载的磁盘,挂载磁盘

linux-centos7操作系统查看系统未挂载的磁盘,挂载磁盘 查看当前磁盘空间 根目录 / 下也只有44G,其他目录只有10几G,正式环境肯定不够用 df -h查看硬盘数量和分区情况 fdisk -l查看到/dev/vdb 有500多G了 将/dev/vdb在分出一个区使用 第一步:编辑分区。执行命令fdisk …...

STM32软件定时器

目录 什么是定时器&#xff1f; 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 …...

[论文阅读] (30)李沐老师视频学习——3.研究的艺术·讲好故事和论点

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…...

Java中List、Set、Map的区别和实现方式

Java中List、Set、Map的区别和实现方式 List List 是一个有序的集合&#xff0c;即元素按照插入的顺序进行排序&#xff0c;可以有重复的元素。因为是有序的&#xff0c;所以可以根据下标来获取元素或者遍历整个集合内的元素。常用的实现类包括 ArrayList 和 LinkedList。 A…...

@EnableScheduling和@Scheduled注解详解fixedrate和fixeddelay的区别

一、pom.xml中导入必要的依赖&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.1.RELEASE</version></parent><dependencies><…...

打印金字塔图案总结

那么好了好了&#xff0c;宝子们&#xff0c;今天给大家总结一下“打印金字塔图案”&#xff0c;来吧&#xff0c;开始整活&#xff01;⛳️ 最近在牛客网上刷题&#xff0c;遇到了这个打印类型的题目&#xff0c;我想总结一下&#xff0c;然后分享给大家。 一、正向金字塔 …...

SQL语句的执行顺序

1、SQL语句的一般执行顺序 1 from 找表 2 on 关联条件帅选 3 join 关联表操作 4 where 条件筛选 5 group by 进行分组 6 avg,sum… 执行函数 7 having 分组后筛选 8 select …...

Debian 版本代号与《玩具总动员》

作为最受欢迎的 Linux 发行版之一&#xff0c;Debian 是许多其他发行版的基础&#xff0c;许多非常受欢迎的 Linux 发行版&#xff0c;例如 Ubuntu、Knoppix、PureOS 、Tails、Armbian 以及 Raspbian&#xff0c;都基于 Debian。 经过近 20 个月的开发&#xff0c;2023 年 6 月…...

TypeScript 第一章

欢迎来到 TypeScript 学习&#xff01;本章将为您介绍 TypeScript 的基础知识。 TypeScript 是 JavaScript 的一个超集&#xff0c;它提供了静态类型检查、类、接口等特性&#xff0c;使得编写大型应用程序变得更加容易和可维护。TypeScript 编写的代码可以被编译成 JavaScript…...

【SpringCloud入门】-- Ribbon入门

1.什么是Ribbon&#xff1f; Ribbon就是netflix公司的一个开源项目&#xff0c;主要功能是提供客户端负载均衡算法和服务调用。Ribbon客户端组件提供了完善的配置项&#xff0c;如连接超时&#xff0c;重试等等。Ribbon作为服务消费者的负载均衡器&#xff0c;有两种使用方式&…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...