创建新项目
对于初学 React 的开发者,首先要面临的问题就是如何搭建一个 React 项目。市面上的工具众多,目前最受 React 社区欢迎的是 Vite。Vite 不仅支持多种库(如 React)与TypeScript 的结合使用,还具备出色的性能。
如果你已经对 React 有所了解,那么可以考虑使用 Next.js 或 Remix 等其他(元)框架作为 Vite 的替代方案。Next.js 最初主要用于服务端渲染,但如今也支持静态站点生成以及其他渲染模式。2023年,Next.js 引入了新的功能——React Server Components,这一功能将 React 组件从客户端迁移到了服务端,从而实现了重大的范式转变。
如果寻求性能卓越的静态内容框架,那么 Astro 是一个理想的选择。它不仅与各种框架兼容,而且能与 React 协同工作。在将内容发送到浏览器时,Astro 仅包含 HTML 和 CSS,即使使用了如 React 这样的框架来创建组件。只有当这些组件变得交互式时,才会请求必要的 JavaScript。
如果你是 React 老手,并希望尝试新的技术,Nitro 或 Waku都是不错的选择。Waku 由 Zustand 的创造者开发,并支持 React Server Components。
建议:
- Vite:适用于客户端渲染的 React 应用
- Next.js:适用于服务端渲染的 React 应用
- Astro:适用于静态生成的 React 应用
包管理
如果你正在寻找在 JavaScript 生态系统中(尤其是React)包管理工具,npm 无疑是首选,因为它与 Node.js 安装捆绑在一起。然而,yarn 和 pnpm 也是值得考虑的优秀替代方案。特别是 pnpm,它提供了更高的性能。
如果有多个相互依赖或共享通用UI组件的React应用,monorepo 的概念可能值得探索。所有上述包管理器都支持使用其内部工作区功能创建 monorepo,但使用 yarn 或 pnpm 时可以获得更好的开发体验。结合诸如 Turborepo 之类的 monorepo 管道工具,可以使整个体验更加顺畅。
建议:
- 选择一个包管理器并坚持使用它
- 默认和最广泛使用的 -> npm
- 性能提高,但相对较新,不那么流行 -> pnpm
- 如果需要 monorepo,使用 Turborepo。
状态管理
React 提供了两个用于管理本地状态的内置 Hooks:useState
和 useReducer
。若要进行全局状态管理,可以利用 React 的 useContext
Hook,它能够将属性从顶级组件安全地传递至其子组件,从而避免了属性传递的问题。
这三个 React Hooks 都赋予了开发者在 React 中实现强大状态管理的能力。可以选择在组件内部使用 useState
/useReducer
Hook 进行协同定位,或者将它们与 useContext
Hook 结合进行全局管理。
如果频繁地使用 React 的 Context
进行全局状态管理,那么 Zustand 可能会是你需要的工具。Zustand 允许管理全局应用状态,任何与 Zustand 存储连接的 React 组件都可以读取和修改这些状态。
尽管 Zustand 已成为社区中的主流选择,但当需要状态管理库时,Redux 仍然是市场上最受欢迎的 React 状态管理工具库。若你选择使用Redux,推荐你一并查看 Redux Toolkit。如果对状态机有特别的兴趣,XState 和 Zag 也是不错的选择。如果需要一个全局存储,但不满意 Zustand 或 Redux,Jotai、Recoil 或 Nano Stores 等本地状态管理解决方案值得考虑。
建议:
- 对于协同定位或共享状态,使用使用内置的
useState
/useReducer
。 - 若需全局状态管理,考虑使用内置的
useContext
。 - 对于大量的全局状态,考虑使用 Zustand 或其替代方案。
数据获取
在处理 UI 状态时,React 的内置 Hook 是非常适用的。然而,当涉及到远程数据的状态管理(包括数据获取和缓存)时,建议使用专门的数据获取库,比如TanStack Query(前身为React Query)。
虽然 TanStack Query 本身并不是一个专门的状态管理库,主要用于从 API 获取远程数据,但它能够处理所有与该远程数据相关的状态管理工作,包括缓存和乐观更新。
如果在 React 中需要更专用的 GraphQL 库,除了 TanStack Query,还可以考虑使用 Apollo Client(流行)、urql(轻量级)或 Relay(由Facebook开发)。
如果希望在 Redux 中集成数据获取和状态管理功能,那么可以考虑使用 RTK Query,它能够将数据获取功能与 Redux 无缝集成,简化状态管理流程。
此外,如果同时开发前端和后端(并且两者都使用TypeScript),那么 tRPC 是一个值得考虑的选项。tRPC 提供端到端的类型安全 API,可显著提高开发效率和用户体验。当需要从前端调用后端时,可以使用类型化的函数。
建议:
- TanStack Query(适用于REST API或GraphQL API),结合 axios 或
fetch
使用 - Apollo Client(适用于 GraphQL API)
- tRPC(适用于紧密耦合的客户端-服务端架构)
路由
如果使用 Next.js 这样的 React 框架,路由已经处理好了。然而,如果使用的是没有框架的React,仅用于客户端渲染(例如 Vite 无 SSR),那么最强大和最受欢迎的路由库是React Router。另一个新的选择是 TanStack Router,它特别考虑了 TypeScript 的支持。
当在 React 中通过 React Router 使用客户端路由时,在路由级别上引入代码分割并不复杂。如果进行此类优化,可以使用@loadable/component
替换React.lazy()
。
建议:
- 最常用的:React Router
- 新兴趋势:TanStack Router
- 主要因其一流的 TypeScript 支持
样式
作为 React 的初学者,可以通过在 JSX 中使用样式对象来从内联样式和简单的 CSS 开始。然而,对于实际应用,应避免频繁使用这种方法。
代码语言:javascript复制
const Headline = ({ title }) =>
<h1 style={{ color: 'blue' }}>
{title}
</h1>
在React 的 JSX 中,虽然可以使用 JavaScript 动态地添加内联样式,但为了保持代码的整洁和可维护性,通常建议将大部分样式放在外部 CSS 文件中。这样,所有的样式规则都可以集中在一个地方,便于管理和修改。
代码语言:javascript复制
import './Headline.css';
const Headline = ({ title }) =>
<h1 className="headline" style={{ color: 'blue' }}>
{title}
</h1>
首先,建议了解一下 CSS 模块。作为众多 CSS-in-CSS 解决方案中的一种,它能够将 CSS 封装到与组件同源的模块中。这样一来,样式就不用担心会不小心泄露到其他组件中。
代码语言:javascript复制
import styles from './style.module.css';
const Headline = ({ title }) =>
<h1 className={styles.headline}>
{title}
</h1>
其次,推荐使用 Styled Components,这是众多 CSS-in-JS 解决方案中的一种,专门为 React 设计。Styled Components(或其替代品如 emotion)允许将使用 JavaScript 创建的样式与 React 组件放在同一文件或相邻文件中。这种方法有助于保持代码的整洁和组织性,并减少样式的意外泄露。
代码语言:javascript复制
import styled from 'styled-components';
const BlueHeadline = styled.h1`
color: blue;
`;
const Headline = ({ title }) =>
<BlueHeadline>
{title}
</BlueHeadline>
第三,推荐使用 Tailwind CSS,这是最流行的实用型 CSS 解决方案。它提供了预定义的 CSS 类,这使得开发人员更高效,并简化了 React 应用的设计系统。然而,使用 Tailwind CSS 需要了解所有预定义的类,并且在某些情况下可能需要冗长的内联样式。
代码语言:javascript复制
const Headline = ({ title }) =>
<h1 className="text-blue-700">
{title}
</h1>
最终选择哪种样式方案取决于你的具体需求和偏好。目前,实用类优先的 CSS(如Tailwind CSS)是主流趋势。如果希望在 React 中根据条件应用样式,可以考虑使用像 clsx 这样的实用库。
建议:
- 实用类优先:Tailwind CSS(最流行)
- CSS-in-CSS:CSS Modules
- CSS-in-JS(不推荐在服务端环境中使用运行时的 CSS-in-JS,因为存在性能问题):Styled Components 或 Facebook 的 StyleX
- CSS-in-TS(支持 TypeScript 和服务端渲染)
组件库
对于初学者来说,亲手构建可复用的组件是极佳的学习经验。无论需要创建一个下拉菜单、选择框、单选按钮还是复选框,都应该学会如何独立地完成这些 UI 组件。
当然,如果你觉得创建所有组件的工作过于繁重,可以选择使用现成的 UI 库。这些库已经准备了许多预先构建的组件,并且它们都遵循相同的设计原则、功能性和无障碍性标准:
- Ant Design
- Material UI(MUI):在自由职业项目中最受欢迎。
- Mantine UI:2022 年最受欢迎。
- Chakra UI:2021 年最受欢迎。
- NextUI:基于 React Aria。
- Park UI:基于 Ark UI。
不过,值得注意的是,UI库的发展趋势正朝向无样式化转变。这些新的库没有固定的样式,但它们具备现代组件库所必需的所有功能和无障碍性。它们经常与像Tailwind这样的实用CSS解决方案配合使用:
- shadcn/ui:2023 年最受欢迎
- Radix
- React Aria
- Catalyst
- Daisy UI
- Headless UI
- Ark UI:来自 Chakra UI 制造商的库。
尽管这些UI库都自带组件,但它们无法像专注于单一UI组件的库那样强大。例如,使用react-table-library 可以在 React 中创建功能强大的表格组件,同时它还提供各种主题(如Material UI),能够轻松地与UI库集成。
动画
在 Web 应用中,所有动画都始于 CSS。但随着需求的发展,CSS 动画可能无法满足需求。这时,开发人员通常会寻求动画库的帮助,它使你能够使用 React 组件进行动画操作。一些广受好评的 React 动画库包括:
- Framer Motion(最推荐)
- react-spring
- react-motion
- react-move
可视化
在 React 中创建图表时,开发人员通常会选择一些预先构建的图表库,以换取更高的灵活性和可定制性。然而,如果希望从头开始创建图表,那么D3是一个无法回避的选择。它是一个基础的可视化库,提供了创建精美图表所需的所有工具。
然而,由于学习 D3 需要投入大量的时间和精力,许多开发人员更倾向于选择一个React图表库。这些库提供了现成的图表、强大的可组合性,并且可以根据需要进行定制。一些流行的 React 图表库包括:
- Echarts
- Recharts
- 现成的图表
- 强大的可组合性
- 可选定制
- visx
- 更倾向于低层次的 D3 而不是高层次的抽象
- 学习难度大
- 现成的图表较多,定制难度较高
- Victory
- nivo
- react-chartjs
表单
在 React 中,最受欢迎的表单库是 React Hook Form。它提供了所需的所有功能:验证(最受欢迎的集成是 zod)、表单提交和表单状态管理。作为替代方案,还有 Formik 和React Final Form 可供选择。
建议:
- React Hook Form:与 zod 集成进行验证
类型检查
React 自带了一个名为 PropTypes
的内置属性验证功能。通过 PropTypes
可以为 React 组件定义属性。如果向组件传递了类型错误的属性,将收到错误消息。
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 的一个重要组成部分,但现在它们已经不再包含在 React 中了。由于历史原因,这里仍然提到了它们,但强烈建议不要使用它。
对于现代的 React 应用,行业标准是使用 TypeScript。如今,几乎所有的新 React 项目都采用 TypeScript,因此建议你也尝试在 React 中使用 TypeScript。
代码语言:javascript复制
type Item = {
id: string;
title: string;
};
type ListProps = {
list: Item[];
};
const List = ({ list }: ListProps) => (
<div>
{list.map((item) => (
<div key={item.id}>{item.title}</div>
))}
</div>
);
如果需要进行更高级的有类型表单验证、API 验证(例如使用 tRPC)等,可以考虑使用 Zod。
建议:
- 如果需要 JavaScript 的类型,就使用 TypeScript。
代码结构
如果希望在 React 项目中采用统一且符合常识的代码风格,强烈推荐使用 ESLint。ESLint是一个强大的代码检查工具,可以强制执行特定的编码标准。例如,可以配置 ESLint 来遵循流行的风格指南(如Airbnb风格指南),以确保代码的一致性和规范性。
同时,如果希望自动化地格式化代码,Prettier 也是一个不错的选择。Prettier是一个无配置项的代码格式化工具,可以轻松集成到编辑器中。每次保存文件时,它会自动格式化代码,使代码更易于阅读和维护。
ESLint 和 Prettier 可以很好地协同工作。ESLint 主要用于检查代码中的错误和潜在问题,而 Prettier 则专注于使代码格式更加一致和易于阅读。因此,结合使用两者可以大大提高代码质量和开发效率。
另外,值得注意的是,随着时间的推移,可能会有新的工具和技术出现并取代 ESLint 和 Prettier 的地位。Biome(前身为Rome)是一个值得关注的新兴工具,它旨在提供一个快速且一体化的代码检查和格式化解决方案。
建议:
- ESLint Prettier
- 给 Biome 一个机会
身份验证
在 React 应用中实现身份验证功能时,通常涉及到用户注册、登录、注销以及可能的密码重置和密码更改等功能。然而,这些功能超出了 React 本身的范围,因为实际的身份验证逻辑通常由后端应用程序处理。
建议使用这些身份验证/后端即服务解决方案中的一种:
- Lucia
- Supabase Auth
- Clerk
- AuthKit
- NextAuth
- Firebase Auth
- Auth0
- AWS Cognito
后端
随着 React 在服务端的应用日益普及,像 Next.js、Astro 或 Remix 这样的元框架成为了 React 项目的理想选择。这些框架提供了构建全栈应用所需的一切,同时充分发挥了React的优势。
如果由于某些原因无法使用全栈框架,但仍然希望使用 JavaScript 或 TypeScript,那么可以考虑使用 tRPC 或 Hono。这两者都是强大的后端解决方案,能够与 React 前端无缝集成。
当然,我们也不能忽视那些传统的后端框架。Express 框架仍然备受推崇,尽管它可能不是最前沿的技术,但其稳定性和成熟度使其成为许多项目的首选。其他值得考虑的选项包括 Fasitfy 和 Nest.js,它们都具有强大的功能和灵活性,能够满足各种后端需求。
数据库
尽管 React 本身并不直接与数据库交互,但随着全栈 React 应用的普及,它与数据库的交互越来越紧密。在开发 Next.js 应用时,可能会遇到数据库对象关系映射器(ORM)。目前最受欢迎的 ORM 是 Prisma。另一个值得考虑的选项是 Drizzle ORM。其他可用的选项包括 Kysely 和 database-js(仅适用于PlanetScale)。
选择合适的数据库时,Supabase 和 Firebase 是两个流行的数据库提供商。Supabase 提供 PostgreSQL,既可自托管也可作为付费服务使用。对于无服务器数据库,PlanetScale、Neon 和 Xata 是值得考虑的替代方案。
测试
测试 React 应用的核心是使用如 Jest 这样的测试框架。Jest 提供了测试运行器、断言库以及其他实用的功能,满足全面测试框架的需求。如果倾向于使用 Vite,Vitest 是一个值得考虑的 Jest 替代方案。
在测试框架中渲染 React 组件时,可以使用 react-test-renderer。这足以进行所谓的快照测试,这是通过 Jest 或 Vitest 进行的。快照测试的工作方式如下:一旦运行测试,会为 React 组件的渲染DOM元素创建快照。在未来的某个时间点再次运行测试时,将创建另一个快照,并使用它与前一个快照进行比较。如果差异不匹配,测试框架会发出警告,可以选择接受快照或调整组件。
随着时间的推移,你可能会发现自己在测试框架环境中使用React Testing Library(RTL)。RTL是一个全面的 React 测试库,可以在测试框架环境中使用。它能够渲染组件并模拟HTML元素上的事件。然后,可以使用测试框架进行断言。
如果正在寻找用于 React 端到端(E2E)测试的测试工具,Playwright 和 Cypress 是最受欢迎的选择。
建议:
- 单元/集成测试:Vitest React Testing Library(最受欢迎)
- 快照测试:Vitest
- E2E测试:Playwright 或 Cypress
不可变数据结构
在 JavaScript 中,原生提供了许多工具来处理数据结构,使其看似不可变。但如果有必要强制使用不可变数据结构,Immer 是一个广受欢迎的选择。
国际化
在为 React 应用进行国际化时,需要考虑的不仅是翻译,还包括复数形式、日期和货币格式化等方面。以下是一些流行的库,可用于处理这些问题:
- FormatJS
- react-i18next
- Lingui
时间处理
当 React 应用需要处理大量日期、时间和时区时,引入一个专门管理这些内容的库是很有用的。以下是一些可用的选项:
- date-fns
- Day.js
- Luxon
桌面应用
Electron 和 Tauri 是跨平台桌面应用的框架。
移动应用
如果想将 React 从 Web 移植到移动平台,React Native 仍然是最佳选择。Expo 作为最流行的框架,可以轻松创建 React Native 应用。而如果需要实现跨 Web 和移动端的统一组件,Tamagui 是一个值得考虑的方案。
文件上传
- react-dropzone
邮件
- react-email
- Mailing
- mjml
拖拽
react-beautiful-dnd 是最受欢迎的 React 拖拽库。dnd kit 是一个流行的替代品,它提供了更多的灵活性和选项,但学习难度也更大。在该领域中,react-dnd 也是一个不错的选择。
VR/AR
React 也可以用于开发虚拟现实 (VR) 和增强现实 (AR) 的应用。大部分库仍处于早期阶段(实验阶段),但以下是与 React 相关的 AR/VR 库:
- react-three-fiber
- react-360
- aframe-react
文档
在编写组件文档时,有许多优秀的 React 文档工具可供选择:
- Storybook
- Docusaurus
- Docz
- Styleguidist
小结
React 生态系统可以被视为 React 的一个框架,但它保持了对 React 的灵活性。这是一个灵活的框架,可以自行决定选择加入哪些库。可以从小处着手,只添加解决特定问题的库。相反,如果 React 就是所需的全部,可以只使用它,保持轻量级。