《2023 年 React 生态》

news2024/11/25 10:53:07

大家好,我是 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 Router
        including 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 someone
        visits an unrecognized URL.
      </p>

      {/* Routes nest inside one another. Nested route paths build upon
            parent route paths, and nested route elements render inside
            parent 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 route
                acts like a catch-all for URLs that we don't have explicit
                routes for. */}
          <Route path="*" element={<NoMatch />} />
        </Route>
      </Routes>
    </div>
  );
}

function Layout() {
  return (
    <div>
      {/* A "layout route" is a good place to put markup you want to
          share 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 for
          the 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.actions

export default counterSlice.reducer

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

import { create } from 'zustand'

type Store = {
  count: number
  inc: () => 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.message

  return (
    <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 it

  return (
    /* "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 生态,以及通过那篇文章了解了大概的生态内容,本文也还有许多不足,比如也许了解的框架还不够,部分内容并未提及到,主要是以我当前水平视角去说,带有一些个人体验感受,可谓是美中不足吧。

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

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

相关文章

ffmpeg(一) ffmpeg+QT开发环境搭建

1、开发库的选择 &#xff08;1&#xff09;音视频开发库 每个主流平台基本都有自己的音视频开发库&#xff08;API&#xff09;&#xff0c;用以处理音视频数据&#xff0c;比如&#xff1a; iOS&#xff1a;AVFoundation、AudioUnit 等 Android&#xff1a;MediaPlayer、Me…

Flink 学习九 Flink 程序分布式运行部署

Flink 学习九 Flink 程序分布式运行部署 1.Job 执行计划 层级说明备注StreamGraph用户代码生成的最初的图程序的运行流程图JobGraph将多个符合条件的节点多个符合条件的节点合并,减少序列化和反序列化ExecutionGraphJobGraph 的并行化调度层的核心数据结构PhysicalGraphJobMa…

【计算机组成原理】信息编码与数据表示

目录 一、进位计数制 二、信息编码 三、定点数的表示 四、校验码 五、浮点数的表示 一、进位计数制 整数部分&#xff1a; 二进制、八进制、十六进制 ---> 十进制&#xff1a;加权求和二进制 ---> 八进制&#xff1a;每三位分为一组&#xff0c;转为八进制…

CloFormer实战:使用CloFormer实现图像分类任务(一)

文章目录 摘要安装包安装efficientnet_pytorch安装timm安装 grad-cam 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文翻译&#xff1a;https://blog.csdn.net/m0_47867638/article/details/131161083 官方源码&#xff1a;https://github.com/qhfan/CloF…

faceswap安装教程图文详解

Faceswap是一种人脸识别技术&#xff0c;可以将一个人的面部特征与另一个人的面部特征进行交换&#xff0c;从而创建出一个看起来像是两个人融合在一起的图像或视频。这项技术可以用于各种目的&#xff0c;包括艺术创作、电影制作、虚拟现实、安全监控等领域。Faceswap的实现方…

UE特效案例 —— 寒冰武器

一&#xff0c;环境配置 创建默认地形Landscape&#xff0c;如给地形上材质需确定比例&#xff1b;添加环境主光源DirectionalLight&#xff0c;设置相应的强度和颜色&#xff1b;PostProcessVolume设置曝光&#xff0c;设置Min/Max Brightness为1&#xff1b; 与关闭Game Sett…

怎样开始用selenium进行自动化测试?

如果您刚开始使用 Selenium 进行自动化测试&#xff0c;以下是建议的步骤。 1、安装 Selenium 首先&#xff0c;您需要安装 Selenium。Selenium 支持多种编程语言&#xff0c;如 Python、Java、C# 等。可以通过 pip 命令在 Python 中安装 Selenium&#xff1a; pip install …

CloFormer实战:使用CloFormer实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整算法设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试热力图可视化展示…

秀米编辑器(xiumi)+百度编辑器(Ueditor) 集成 :解决集成问题,秀米编辑器导出到百度编辑器格式问题,图片保存到自己的服务器(阿里云OSS)

1.集成前提条件&#xff1a; 1. 需要集成百度编辑器到环境中 2.https环境下才可以导出数据到百度编辑器&#xff0c;如果不是https环境&#xff0c;会出现错误 然后我们开始讲解如何集成&#xff1a; 2.引入资源&#xff1a; //百度编辑器需要修改的文件&#xff08;配置与原始…

测试入门第一步------编写接口测试用例

自动化始终只是辅助测试工作的一个手段&#xff0c;对于测试人员而言&#xff0c;测试基础和测试用例的设计才是核心。如果测试用例的覆盖率或者质量不高&#xff0c;那将这部分用例实现为自动化用例的意义也就不大了。 那么&#xff0c;接口测试用例应该怎么编写呢&#xff1…

Spring boot集成RabbitMq

Spring boot集成RabbitMq 一、搭建RabbitMq1.1 参考1.2 配置erlong的环境变量1.3 RabbitMQ对应的在注册表中的位置 二、使用教程2.1 打开服务端2.2 注意的问题2.3 Queue的包 三、git命令3.1 git remote3.2 git remote add origin "xxxx"3.3 git push -u origin maste…

使用esp32+micropython+microdot搭建web(http+websocket)服务器(超详细)第一部分

使用esp32micropythonmicrodot搭建web(httpwebsocket)服务器&#xff08;超详细&#xff09;第一部分 microdot文档速查 什么是Microdot?Microdot是一个可以在micropython中搭建物联网web服务器的框架micropyton文档api速查 Quick reference for the ESP32 先来个小demo先体…

数据仓库——原理+实战(一)

一、数据仓库概述 1. 数据仓库诞生原因 &#xff08;1&#xff09;历史数据积存&#xff08;存放在线上业务数据库中&#xff0c;当数据积压到一定程度会导致性能下降&#xff0c;所以需要将实用频率低的冷数据转移到数据仓库中&#xff09; &#xff08;2&#xff09;企业数…

【C++11】线程库

文章目录 1. get_idthis_thread 2. 锁1. 为什么要使用锁&#xff1f;2. 锁的使用并行 与 串行递归锁 recursive_mutextimed_mutexlock_guard 与 unique_lock 3. atomic4. 条件变量线程等待线程唤醒条件变量的应用问题1&#xff1a;如何保证 v1先运行&#xff0c;v2阻塞&#xf…

python的tqdm一些操作

主要参数 iterable: 可迭代的对象, 在手动更新时不需要进行设置 desc: str, 左边进度条的描述性文字 total: 总的项目数 leave: bool, 执行完成后是否保留进度条 file: 输出指向位置, 默认是终端, 一般不需要设置 ncols: 调整进度条宽度, 默认是根据环境自动调节长度, 如果设置…

VUE 2X 事件处理 ⑤

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs E v e n t j s Eventjs Eventjs总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ ⡖⠒⠒⠒⠤⢄⠀⠀⠀…

MySQL面试题--聚簇索引,非聚簇索引,回表查询

目录 概念 聚集索引选取规则: 面试回答 大纲 回答 概念 分类 含义 特点 聚集索引(Clustered Index) 将数据存储与索引放到了一块&#xff0c;索引结构的叶子节点保存了行数据 必须有,而且只有一个 二级索引(Secondary Index) 将数据与索引分开存储&#xff0c;索引…

进程的引入(操作系统)

目录 1、进程的概念 2、进程状态及状态转换 &#xff08;1&#xff09;进程的状态 &#xff08;2&#xff09;状态的转换 3、进程控制块&#xff08;PCB&#xff09; 4、进程的组成和上下文 5、进程的队列 6、进程的类型和特征 7、进程间相互联系与相互作用 8、进程的…

pcl1.12.1重新安装boost库

因为我的库有问题&#xff0c;直接使用pcl1.12.1的时候报错&#xff0c;于是重新安装boost库 1.78.0地址(因为打开pcl1.12.1的安装目录&#xff0c;发现boost库是1.78.0&#xff0c;所以去官网找到对应的版本进行安装) Index of main/release/1.78.0/sourcehttps://boostorg.j…

OpenHarmony端云一体化应用开发快速入门练习(中)登录认证

一、登录认证手机 可以在应用中集成手机帐号认证方式&#xff0c;您的用户可以使用“手机号码密码”或者“手机号码验证码”的方式来登录您的应用。 &#xff08;一&#xff09;前提条件 需要在AGC控制台开通认证服务。 需要先在您的应用中集成SDK。 &#xff08;二&#xff…