给大家推荐一个好用的一个状态管理库——Recoil
,以react为主的同学用起来会非常舒服。
什么是 Recoil
Recoil 是一个由 Facebook 开发的 React 状态管理库,它提供了一种简单而强大的方式来管理 React 应用中的状态。旨在简化和统一 React 应用中的状态管理。与其他状态管理库相比,Recoil 提供了更简单、更直观的 API,并且与 React 的生态系统紧密集成。
Recoil 体验
准备
使用 Recoil,需要目最外层包一个 RecoilRoot
import React from 'react';
import { RecoilRoot } from 'recoil';
function App() {
return (
<RecoilRoot>
...
</RecoilRoot>
);
}
状态共享atom
新建一个文件store
专门存放atom
。
然后通过 atom
来定义一个状态。
export const countState = atom({
key: "countValue",
default: 0
});
在任何需要使用这个状态的文件下
import React from "react";
import { useRecoilState } from "recoil";
import { countState } from "../store";
const App = () => {
const [count, setCount] = useRecoilState(countState);
return <>
<div>{count}</div>
<button onClick={()=>setCount(count+1)}>add</button>
</>;
};
export default App;
没错,看起来很熟悉,他就像一个可以全局使用的useState
,这就是recoil
最基本的用法
派生状态selector
当我们的一个状态依赖另外一个状态时就可以使用selector
const countTwoSelector = selector({
key: "countTwoValue",
get: ({get}) => {
// 通过 get 可以读取其它状态
const ctv = get(countValue) + 1;
return ctv;
},
});
这里get()
也支持异步,可以返回promise
const asynCountTwoSelector = selector({
key: "asyncCountTwoValue",
get: async({get}) => {
const ctv = await getCountTwo();
return ctv;
},
});
在读取selector
的值时,会根据get()
函数同步异步也会所不同。
同步时与atom
使用方法一致;
异步时,要使用useRecoilValueLoadable
import React from "react";
import { useRecoilState } from "recoil";
import { asynCountTwoSelector } from "../store";
const App = () => {
//cTLoadable三种状态`hasValue`、`loading`、`hasError`
const [cTLoadable, setCT] = useRecoilValueLoadable(asynCountTwoSelector);
switch (cTLoadable.state) {
case 'hasValue':
return <div>{cTLoadable.contents}</div>;
case 'loading':
return <div>Loading...</div>;
case 'hasError':
throw cTLoadable.contents;
}
};
export default App;
有get()
肯定也有set()
,一个读取值、一个设置值;用法大同小异,具体细节大家可以参考官方文档。
其他api
除此之外,还有很多api
useRecoilValue
这个时候,当前组件对于countState
是只读的
const countValue = useRecoilValue(countState);
useSetRecoilState
这个时候,当前组件对于countState
是只写的,这里会有一个好处就是因为是只写的,所以当前组件不会因为改变状态值而导致当前组件更新
const setCountValue = useSetRecoilState(countState);