2022 年的 React 生态
React 是用于构建用户界面的JavaScript库,其核心是让开发者能够使用函数组件创建组件驱动的用户界面。它带有一些内置解决方案,例如,用于本地状态、副作用和优化性能的 React Hooks,但这些只能处理函数(组件和Hook)以创建 UI。React 拥有一个庞大的生态系统,可以帮助开发人员更快地实现复杂的UI。本文就来看看 React 最新的生态系统,以实现快速技术选型!
创建项目
在 React 社区中,最受欢迎的创建 React 项目的工具就是 Vite,它允许使用各种库(例如 React)+ 可选的 TypeScript 组合创建项目,它具有强大的性能。
如果你已经熟悉 React,可以选择最流行的(元)框架之一 Next.js 作为替代,它建立在 React 之上。 这个领域中另一个流行但较新的框架是 Remix。
虽然 Next.js 最初用于服务端渲染(Web 应用),但它也可用于静态站点生成。 但是,如果正在寻找一个考虑到静态内容最佳性能的框架,可以考虑使用 Astro,它与框架无关,因此可以与 React 一起使用。
建议:
- Vite:用于客户端 React 应用;
- Next.js :用于服务器端渲染的 React 应用;
- Astro:用于静态站点生成的 React 应用。
包管理器
JavaScript 生态系统(以及 React)中默认且使用最广泛的包管理器就是 npm。 在 React 应用中安装依赖项时,通常会使用 npm。 然而,在过去几年中,yarn 一直是一个成功的替代品。 另外,pnpm 是一个最新的替代品,它带来了巨大的性能提升。
如果碰巧创建了多个相互依赖或共享一组通用自定义 UI 组件的 React 应用,可能需要了解 monorepo 的概念。前面提到的所有包管理器都允许开发者使用其内部工作区功能创建 monorepos。但是,使用 yarn/pnpm 可以获得最好的开发体验。 结合 Turborepo 等 monorepo 工具,monorepo 体验变得更完美。
建议
- 选择一个包管理器并坚持使用;
- npm:默认且使用最广泛;
- 如果是 monorepo,使用 Turborepo。
状态管理
React 提供了两个内置的 Hook 来管理本地状态:useState
和 useReducer
。如果需要全局管理状态,可以选择使用 React 内置的 useContext
Hook,在不使用 props
的情况下将 props
从顶级组件传递到下面的组件,从而避免 props drilling 的问题。这三个 hooks 使开发人员能够在 React 中实现强大的状态管。
如果需要过于频繁地使用 React 的 Context 来处理共享/全局状态,那么可以考虑使用最流行的状态管理库:Redux。 它可以管理全局应用状态,可以由连接到其全局 store 的任何 React 组件进行读取和修改。如果使用 Redux,可以了解一下 Redux Toolkit。它在 Redux 的核心之上提供了一个很棒的 API,极大地改善了开发人员使用 Redux 的体验。
作为替代方案,如果喜欢全局存储的总体思路但不喜欢 Redux 的实现方式,可以使用其他流行的本地状态管理解决方案,例如 Zustand、Recoil、XState 或 Jotai。
建议
- useState/useReducer:用于本地状态管理;
- useContext:用于小的全局状态管理;
- Redux:用于大的全局状态管理(或替代方案)。
数据获取
React 的内置 Hook 非常适合 UI 状态,但是当涉及到远程数据的状态管理(以及数据获取)时,建议使用专用的数据获取库,例如 TanStack Query(以前称为 React Query)。 虽然 TanStack Query 本身不被视为状态管理库,因为它主要用于从 API 获取远程数据,但它会处理此远程数据的所有状态管理(例如缓存、乐观更新)。
TanStack Query 专为使用 REST API 而设计,现在它也支持 GraphQL。 但是,如果正在为 React 前端寻找专用的 GraphQL 库,请查看 Apollo Client(流行)、urql(轻量级)或 Relay(Facebook 提供)。
如果已经在使用 Redux 并希望在 Redux 中添加具有集成状态管理的数据获取,而不是添加 TanStack Query,可能考虑使用 RTK Query,它将数据获取巧妙地集成到 Redux 中。
另外,如果可以控制 TypeScript 编写的后端,可以考虑使用 tRPC 以获得端到端类型安全 API。
建议
- TanStack Query(REST API、GraphQL API);
- axios:数据获取库;
- Apollo Client(GraphQL API);
- tRPC:端到端类型安全。
路由
如果使用的是像 Next.js 这样的 React 框架,那么路由已经处理好了。如果在没有框架的情况下使用 React,并且仅用于客户端渲染(例如没有 SSR 的 Vite),那么最强大和最流行的路由库就是 React Router。考虑到完全支持 TypeScript 的新替代方案是 TanStack Router。
如果在带有 React Router 的 React 中使用客户端路由,那么在路由级别引入代码拆分是很容易的。 如果需要进行代码拆分,可以用 @loadable/component 来替代 React.lazy() ,这会给你更好的用户体验和更多的选择。
建议
- React Router
- 如果喜欢 TypeScript 和 TanStack Query,可以考虑使用 TanStack Router,但是它相对较新。
CSS样式
对于 React 初学者,通过在 JSX 中使用样式对象来开始使用内联样式和简单的 CSS 是很好的:
const Headline = ({ title }) =>
<h1 style={{ color: 'blue' }}>
{title}
</h1>
内联样式可用于在 React 的 JSX 中使用 JavaScript 动态添加样式,而外部 CSS 文件可以保存 React 应用的所有剩余样式:
import './Headline.css';
const Headline = ({ title }) =>
<h1 className="headline" style={{ color: 'blue' }}>
{title}
</h1>
当应用不断增长时,还有许多其他样式实现方式。 首先,建议将 CSS Module作为众多 CSS-in-CSS 解决方案之一。 Vite 支持 CSS Module,它提供了一种将 CSS 封装到组件范围模块中的方法。这样,它就不会意外地泄漏到其他 React 组件的样式中。 虽然应用的某些部分仍然可以共享样式,但其他部分不必访问它。在 React 中,CSS Module 通常是将 CSS 文件与 React 组件文件放在一起:
import styles from './style.module.css';
const Headline = ({ title }) =>
<h1 className={styles.headline}>
{title}
</h1>
其次,推荐 Styled Components 作为 React 的众多 CSS-in-JS 解决方案之一。
import styled from 'styled-components';
const BlueHeadline = styled.h1`
color: blue;
`;
const Headline = ({ title }) =>
<BlueHeadline>
{title}
</BlueHeadline>
第三,推荐 Tailwind CSS 作为最流行的 Utility-First-CSS 解决方案。 它带有预定义的 CSS 类,无需自己定义即可使用。 这可以提高开发人员的效率,并简化了 React 应用的设计系统,但需要权衡了解所有类和许多 CSS 类的冗长内联:
const Headline = ({ title }) =>
<h1 className="text-blue-700">
{title}
</h1>
无论选择 CSS-in-CSS、CSS-in-JS 还是 Utility-First-CSS 都取决于具体场景。这些策略适用于更大的 React 应用。 如果想在 React 中有条件地应用一个类名,可以使用像 clsx 这样的实用程序。
建议
- CSS-in-CSS:CSS Module
- Utility-First-CSS:Tailwind CSS
- CSS-in-JS:Styled Components(最受欢迎)、Emotion(备选方案)
- 条件 CSS 类:clsx
UI组件库
如果希望使用一个 UI 组件库,它包含许多共享相同设计系统的预构建组件。以下所有 UI 库都带有基本组件,如按钮、下拉菜单、对话框和列表:
- Ant Design(最推荐)
- Material UI(最受欢迎)
- Mantine UI(最推荐)
- Chakra UI (最推荐)
- Radix (无样式设计系统)
- Tailwind
- Headless UI
- Daisy UI
- Tailwind UI (非免费)
- Semantic UI
- React Bootstrap
- Reactstrap
- NextUI
- Primer
尽管这些 UI 组件库都带有许多内置组件,但它们无法使每个组件都像只专注于一个 UI 组件的库一样强大。 例如,react-table-library 可以在 React 中创建强大的表格组件,同时还提供主题(例如 Material UI),以便很好地融入流行的 UI 组件库。
动画
有时 CSS 动画无法满足我们的需求。可以尝试使用 React Transition Group,这使开发人员可以使用 React 组件执行动画。 其他著名的 React 动画库如下:
- Framer Motion (最推荐)
- react-spring(经常推荐)
- react-motion
- react-move
- Animated (React Native)
可视化
如果想从头开始构建图表,可以尝试使用 D3。它是一个基础可视化库,提供了创建图表所需的一切。如果只是想选择了一个现成的 React 图表库,下面是一些流行的解决方案:
- 推荐: Recharts (出色的可组合性)
- visx(学习难度大)
- 现成的图表,较难定制:
- Victory
- nivo
- react-chartjs
表单
React 中最流行的表单库是 React Hook Form。 它带有从验证(最流行的集成是 zod)到提交到表单状态管理所需的一切。 替代方案有 Formik 和 React Final Form。 如果已经在使用了 React UI 库,可以查看它们内置的表单解决方案。
建议
- React Hook Form
- 与用于验证的 zod 集成
- 如果使用 UI 库,可以检查内置表单是否满足所有需求
- React Hook Form 带有一个干净的 API,用于 UI 库集成
类型检查
React 带有一个名为 PropTypes 的内部类型检查。 通过使用 PropTypes,可以为 React 组件定义 props。 每当将错误类型的 prop 传递给组件时,将在运行应用时收到错误消息:
import PropTypes from 'prop-types';
const List = ({ list }) =>
<div>
{list.map(item => <div key={item.id}>{item.title}</div>)}
</div>
List.propTypes = {
list: PropTypes.array.isRequired,
};
但是,PropTypes 不再包含在 React 核心库中。 在过去的几年里,PropTypes 变得不那么流行了,取而代之的是 TypeScript:
type Item = {
id: string;
title: string;
};
type ListProps = {
list: Item[];
};
const List: React.FC<ListProps> = ({ list }) =>
<div>
{list.map(item => <div key={item.id}>{item.title}</div>)}
</div>
如果想在 React 中接受类型,TypeScript 是目前的最佳选择。如果想超越 TypeScript 进行类型化表单验证、API 输入/输出验证等,可以使用 Zod。
建议
- 如果需要类型化的 JavaScript,请使用 TypeScript。
风格和格式
如果想拥抱统一的代码风格,可以在 React 项目中使用 ESLint。 ESLint 等 linter 在 React 项目中强制执行特定的代码风格。例如,可以要求 ESLint 遵循流行的风格指南(例如 Airbnb 风格指南)。 可以将其与 ESLint 与 IDE/编辑器集成,它会指出每个错误。
如果想拥抱统一的代码格式,可以在 React 项目中使用 Prettier。 它是一个代码格式化程序,只有少数可选配置。 可以将它集成到编辑器或 IDE 中,以便在每次保存文件时格式化代码。尽管 Prettier 并没有取代 ESLint,但它与 ESLint 集成得很好。
建议
- ESLint + Prettier
身份验证
在 React 应用中,如果希望引入具有注册、登录和注销等功能的身份验证。通常还需要其他功能,如密码重置和密码更改功能。这些功能远远超出了 React 的范畴,因为后端应用会管理这些事情。
由于身份验证会带来很多安全风险和并非人人都知道的细节,建议使用现有的身份验证/后端即服务解决方案:
- Firebase Auth
- Supabase Auth
- Auth0
- AWS Cognito
建议
- 选择身份验证服务或 BaaS(例如 Firebase/Supabase)
部署和托管
可以像任何其他 Web 应用一样部署和托管 React 应用。 如果想完全控制,可以选择 Digital Ocean。 如果想让托管服务处理所有事情,Netlify 或 Vercel(尤其是 Next.js)是流行的解决方案。 如果已经在使用第三方后端作为 Firebase/Supabase 等服务,可以检查他们是否也提供托管服务。其他流行的托管服务提供商有 Render、Fly.io 或 Railway。
测试
可以使用 Jest 这样的测试框架来测试 React 应用。 它提供了测试运行程序、断言库等功能,综合了测试框架所需的一切。 如果你是 Vite 的粉丝,可以使用 Vitest 作为 Jest 替代品。
可以使用 react-test-renderer 在测试框架中渲染 React 组件。这已经足以使用 Jest 或 Vitest 执行快照测试。 快照测试的工作方式如下:运行测试后,将创建 React 组件的渲染 DOM 元素的快照。 当在某个时间点再次运行测试时,将创建另一个快照,用作前一个快照的差异。如果差异不相同,测试框架会报错,要么必须接受快照,要么更改组件的实现。
React Testing Library (RTL) 是一个比较流行的 React 测试库,RTL 使渲染组件和模拟 HTML 元素上的事件成为可能。之后,可以使用测试框架(例如 Jest/Vitest)用于 DOM 节点上的断言。
如果正在寻找用于 React 端到端 (E2E) 测试的测试工具,Playwright 和 Cypress 是最受欢迎的选择。
建议
- 单元/集成测试:Jest/Vitest + React Testing Library(最受欢迎)
- 快照测试:Jest/Vitest
- E2E 测试:Playwright、Cypress
不可变数据结构
原生 JavaScript 提供了大量内置工具来处理数据结构,就好像它们是不可变的一样。 但是,如果需要使用不可变数据结构,那么最受欢迎的选择之一就是 Immer。
国际化
当涉及到 React 应用的国际化 i18n 时,不仅需要考虑翻译,还需要考虑多元化、日期和货币的格式等。 这些是处理它的最受欢迎的库:
- FormatJS
- react-i18next
富文本编辑器
React 中的富文本编辑器:
- Draft.js
- Slate.js
- ReactQuill
时间
近年来,JavaScript 本身在处理日期和时间方面变得非常棒,如果 React 应用需要大量处理日期、时间和时区,可以引入一个库来管理这些东西。
- date-fns
- Day.js
- Luxon
桌面应用程序
Electron 仍然是跨平台桌面应用程序的首选框架。 还有一些替代方案,例如:
- Tauri(很好的选择,非常受欢迎)
- Neutralino.js
- NW.js
文件上传
- react-dropzone
- filepond
移动开发
将 React 从 Web 带到移动设备的首选解决方案是 React Native。
VR/AR
使用 React 可以深入虚拟现实或增强现实。现成的解决方案包括:
- react-three-fiber
- react-360
- aframe-react
组件文档
编写组件文档的解决方案包括:
- Storybook
- Docusaurus
- Docz
- Styleguidist