2021 年我的首选 React 库
状态管理
UI 组件
测试
奖励:表单库
我从事 React 应用开发已经三年多了,用过很多库来构建各种应用。过去几个月对 React 生态系统来说可谓硕果累累!我们看到许多不同的工具正在慢慢取代数百名开发者多年来用来构建应用的旧库。今年我为客户启动了一个新项目,有机会测试这些新工具,并为 2021 年及以后的选择奠定了新的技术栈。
状态管理
我在很多项目中都用过Redux,它曾经是(或者曾经是?)一个很棒的应用程序数据集中化解决方案。但有些地方感觉过于复杂,开发者们对此抱怨已久。例如,学习Flux 模式对某些人来说可能相当困难。然后有人告诉你,你需要使用中间件来处理副作用。太好了!那就用Redux Thunk吧。但是等等,现在有人告诉你还有一个更好的解决方案:Redux Saga。太棒了!这下更复杂了。
但 2020 年情况发生了变化,新的挑战者出现了。你可能听说过Recoil、Jotai、Zustand或React Context API。但让我放弃 Redux 的是:
对于那些已经了解它的人来说,你可能会说它不像 Redux。它做的事情不一样。React Query是一个数据获取库,它使获取、缓存、同步和更新服务器状态变得简单。
我参与的所有项目都使用 Redux 来存储来自服务器的数据。这也是 Thunk 或 Saga 等中间件出现的原因。
如果我告诉你,有一个库可以做到这一点,而无需操心 action、action creator、reducer 等等……你会怎么想?使用 React Query,你可以轻松地从服务器获取数据并缓存。之后,你可以使数据失效,然后所有内容都会自动重新获取并存储。你唯一需要担心的是如何获取数据。当然,它还会返回 isLoading 布尔值(以及大量其他你不想自己处理的信息)。
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<FirstComponent />
<SecondComponent />
</QueryClientProvider>
)
}
function FirstComponent() {
// fetch some data
const { isLoading, error, data } = useQuery('myData', fetchData)
if (isLoading) return 'Loading...'
if (error) return 'An error has occurred: ' + error.message
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
</div>
)
}
function SecondComponent() {
const queryClient = useQueryClient()
const invalidateData = () => {
// invalidate data, will trigger a refetch in FirstComponent
queryClient.invalidateQueries('myData')
}
return (
<div>
<button onClick={invalidateData}>
Click me to refetch data !
</button>
</div>
)
}
如果您仍然需要处理复杂的本地状态(即不是来自您的服务器),那么我可以为您提供一些东西!
Zustand是一个小巧快速的状态管理解决方案。我不太喜欢像 Redux 这样基于上下文的库。它对我来说总感觉像黑魔法:你根本不知道它是怎么运作的,但它确实管用🤷♂️。我并不是说基于上下文的状态管理不好,我只是说,即使它是 React 的一个特性,整个 Provider/Consumer 对我来说也感觉不太自然。
我喜欢 Zusand 的原因是它只是对象!您可以从对象创建状态,它可以包含字符串、数字、布尔值或其他任何属性,就像使用 Redux 一样。但是,如果您想自己处理,也可以放置函数来更新状态甚至获取数据(请尝试 React Query。您不会失望的)。Zusand
还为您提供了一个钩子,您可以在组件中使用它来访问数据。但很酷的是:您也可以在组件之外访问它!您可能知道,如果您不在组件中,则无法使用钩子,但 Zusand 使您能够访问状态对象以及使用钩子可以做的所有其他事情。这对于测试非常有用,您只需在渲染组件之前管理状态,而不必用上下文包装所有内容。
import create from 'zustand'
const useStore = create(set => ({
bears: [],
fetchBears: async () => {
const response = await fetch('/bears')
set({ bears: await response.json() })
}
}))
export default function App() {
const bears = useStore(state => state.bears)
return <h1>{bears.length} bears around here ...</h1>
}
// You can also use your store outside of components
// Getting non-reactive fresh state
const bears = useStore.getState().bears
// Listening to selected changes, in this case when "bears" changes
const unsub = useStore.subscribe(console.log, state => state.bears)
// Updating state, will trigger listeners
useStore.setState({ bears: [{ name: 'zustand' }] })
// Unsubscribe listeners
unsub()
// Destroying the store (removing all listeners)
useStore.destroy()
我还没有尝试过其他替代品,比如 Recoil 或 Jotai,但通过阅读它的文档,我觉得 Zustand 是最简单、最自然的,到目前为止我并没有失望。
UI 组件
当你没有严格的样式规范时,你最终可能会使用组件库来整合那些已经很好地组合在一起的组件。大多数情况下,组件库还会提供额外的功能,并删除大量的样板代码。
我最初使用Reactstrap(即 Bootstrap for React),后来切换到了Material UI。后来我放弃了 Reactstrap,因为 Bootstrap 已经不再流行,而 Material UI 才刚刚流行。但使用 Material UI 时,我却感到沮丧。对我来说,它的组件并不总是直观或灵活,而且我花了太多时间在文档中搜索一些简单的东西。Material UI 对我来说并不合适。所以我寻找替代方案,结果发现:
Ant Design是一个面向企业级产品的设计系统。它包含了所有你需要的组件。每当我思考“我能用组件实现这个功能吗?”时,我都能做到。
它的文档非常完善,包含大量示例。阅读文档,你能感受到大家对哪些功能可能有用进行了长时间的思考。
Ant Design 仍有一些我不太喜欢的地方。它的样式是用LESS编写的,而我更喜欢SASS(create-react-app 默认支持 SASS)。如果要自定义 Ant Design 主题,则需要使用 LESS 或工具在构建过程中更改 LESS 变量。对我来说,仅仅更新颜色变量有点太麻烦了。
另外需要注意的是,Ant Design 是一个设计系统,它应该有自己的一套原则。它规定了使用组件时需要遵循的规则,而当你想要在这些用例之外使用组件时,它并不容易。总的来说,与 Material UI 相比,Ant Design 的使用体验更好,我可以轻松地完成所有需要做的事情,而不会感到任何挫败感。
测试
我被介绍使用Enzyme来测试 React 应用程序。在过去,这可能是最好的解决方案。但随着时间的推移,出现了一个非常强大的替代方案:
测试库 (Testing Library)已经存在一段时间了,并且已经逐渐取代了 Enzyme。
该工具提供了简单而完整的测试实用程序,鼓励良好的测试实践。与 Enzyme 不同,它更接近用户与应用程序的交互方式,让您对应用程序的测试方式更有信心。
最让我震惊的是测试的可读性。只需查看代码就能确切地知道它的作用。这听起来可能有点傻,但 Enzyme 并非总是如此。
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import MyComponent from './MyComponent'
test('display "Hello dev.to"', () => {
const { getByText } = render(<MyComponent />)
expect(getByText('Hello dev.to')).toBeInTheDocument()
})
test('display "Clicked !" after clicking on button', () => {
const {getByText, queryByText} = render(<MyComponent />)
expect(queryByText('Clicked !')).not.toBeInTheDocument()
fireEvent.click(screen.getByText('Click me'))
expect(getByText('Clicked !')).toBeInTheDocument()
})
测试库不仅适用于 React,它还支持所有框架,并为 Cypress 等工具提供实用工具。无需多言,在 2021 年,如果不使用测试库,你根本无法启动 React 应用程序。
奖励:表单库
如果您不使用组件库(通常有一些组件来管理表单),您可能需要一些东西来处理您的表单。
在过去的几年里,我们看到许多库试图提供一种简单的表单处理方法。你可能听说过Redux Form(千万别),Formsy或Formik。我都试过了,但最终让我信服的是:
React Hook Form是一个非常简单的基于 Hook 的库,数据验证非常简单。根据他们的基准测试,它比其他替代方案速度更快。通过使用 Hook,React Hook Form 的使用体验非常自然,它还使用 refs(即不受控制的输入)从字段中获取值,因此它基本上是标准的 JavaScript。Formik
是另一个不错的替代方案,但对我来说感觉更复杂。
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
const onSubmit = 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>
);
}
你呢 ?
你最近用过新的库吗?还是还在用那些老旧的?在评论区留言告诉我吧!我很想知道我是否错过了哪些好工具😄
文章来源:https://dev.to/sfeircode/my-go-to-react-libraries-for-2021-4k1