react一些好用的库或方法
![]()
guojiabing
大佬推荐了一些比较优秀的库,这里做一些笔记,防止忘记!
ahooks
a就是alibaba 的第一个字母,也就是阿里加的产品!
它内置了一堆好用且实用的hooks!
useRequest
封装的http请求hook
// 同步xxx,其中返回值都是响应式的状态
const { data, loading, run } = useRequest(xxxPromise/apiUrl,{
ready: Boolean(xxx), // 当有值后才会请求
refreshDeps: [xxx], // 依赖项目变动则会更新请求
}
);
- 设置返回值:通过返回的 mutate,可以手动更新data的值,如
mutate(xxx) - 手动触发:通过配置项manual = true,ready=true,再手动调返回的run方法
useControllableValue
可控状态,能给你一个“双向数据流”的感觉,即属性可以在子组件修改生效!
这里有一篇专门的文章!
ts-pattern
在tsx中,如果条件渲染过于复杂,则需要大量的三元运算符参与,看起来及其不优雅!
ts-pattern 正是来解决这个问题的!

import { match, P } from 'ts-pattern';
type Data =
| { type: 'text'; content: string }
| { type: 'img'; src: string };
type Result =
| { type: 'ok'; data: Data }
| { type: 'error'; error: Error };
const result: Result = ...;
const html = match(result)
.with({ type: 'error' }, () => <p>Oups! An error occured</p>)
.with({ type: 'ok', data: { type: 'text' } }, (res) => <p>{res.data.content}</p>)
.with({ type: 'ok', data: { type: 'img', src: P.select() } }, (src) => <img src={src} />)
.otherwise(() => null)
immerjs
immerjs 不可变数据辅助库!
抛出问题
我们先来看一段代码,如下,当你点击完更新之后,再点击重制也回不去了!
这就是因为原始数据 personInit 应为 不可变数据,而你在调用update的时候给它改变了!
import { useState } from 'react';
const personInit = {
id: 20250101,
name: '张三',
age: 20,
};
const DemoThree = () => {
const [person, setPerson] = useState(personInit);
const update = () => {
person.name = '李四';
setPerson({...person});
};
const reset = () => {
setPerson({...personInit});
};
return (
<div className="wrapper">
<div className="info">{JSON.stringify(person)}</div>
<div className='flex gap-1'>
<button onClick={update} className='bg-blue-400 text-white p-1 rounded'>更新</button>
<button onClick={reset} className='bg-blue-400 text-white p-1 rounded'>重制</button>
</div>
</div>
);
};
export default DemoThree;
自己解决
其实解决办法也简单,我们做个深拷贝即可,其它都不变的情况下,修改如下
import _ from 'lodash';
// 封装 change 函数
const change = (state, updater) => {
// 创建状态的深拷贝
const nextState = _.cloneDeep(state);
// 应用更新函数
updater(nextState);
return nextState;
};
const DemoThree = () => {
const [person, setPerson] = useState(personInit);
const update = () => {
const newPerson = change(person, (draft) => {
draft.name = '李四';
});
setPerson(newPerson);
};
const reset = () => {
setPerson({ ...personInit });
};
// ...其它保持不变
}
使用三方库
如果我们不想自定义change函数,那么 immer 库就提供了这么一个函数!
import {produce} from "immer"
const update = () => {
const newPerson = produce(person, (draft) => {
draft.name = '李四';
});
setPerson(newPerson);
};
当然这样来看,和我们自定change解决方案使用起来没什么太大区别,
进阶用法,结合react,immer提供了一个更好的钩子!
import { useImmer } from "use-immer";
const [person, setPerson] = useImmer(personInit);
const update = () => {
setPerson((draft) => {
draft.name = '李四';
});
};
const reset = () => {
setPerson({ ...personInit });
};
除此之外,使用immer的好处在于它 仅仅当内容发生变化时才会设置为新对象,否则依然是原对象(的引用),进而不会导致无用的reRender

浙公网安备 33010602011771号