Skip to content
快速导航

Recoil快速上手

前言

React状态库太多了,不知道用哪个?回想起来有ReduxMobX,这篇我想和你分享一下爽到起飞的Recoil

Recoil介绍

Recoil是什么

学习目标:了解Recoil是什么?

Recoil官网:Recoil

RecoilFacebook推出的一个专门针对React的状态管理库,Recoil的全部 API 都是以Hook方式提供,使用起来非常方便,可以大大降低学习成本。还有一点,它只支持函数式组件,对于类组件可能要说拜拜了

Recoil的特点

学习目标:了解Recoil的优势特点

**说在前面:**在学习React之后我们知道,可以使用React内置的Context机制+状态提升+(useReducer)来进行全局状态管理,但是这样的话会有一些毛病,例如:组件间的状态共享只能通过将state 提升至它们的公共祖先来实现,但这样做可能导致重新渲染一颗巨大的组件树等等。。。。。。Recoil可以改善这些问题!

特点有哪些?

  • 只支持Hook方式,使用风格和React 完全一致,没有新的语法学习负担
  • 推崇状态分散管理,推崇Minimal,也就是最小粒度化,
  • 状态的定义是渐进式和分布式的,可以对代码进行分割
  • 支持Concurrent Mode(这个不了解也没事,先不用理会)

Recoil快速使用

环境初始化

推荐使用React官方提供的脚手架创建项目,如果你看过我之前的React快速上手就应该还有着my-app项目

npx create-react-app my-app // my-app是我们的项目名字
cd my-app // 进入项目
npm start // 启动!!!React来哩

目录调整

首先删除多余的文件,剩个App.jsindex.js就可以了

然后在新的项目中新添加如下文件和文件夹:

  • src
    • components
      • TextInput.js
      • CharCount.js
    • store
      • index.js

安装Recoil

bash
npm install recoil
# 或者
yarn add recoil

RecoilRoot(状态作用域)

首先是引入RecoilRoot并将其放在根组件的位置(也可以放在其他父组件位置上),是不是很像Context?没错,底层也是这么实现的

javascript
import { RecoilRoot } from 'recoil';
export default function App() {
  return (
    <RecoilRoot>
      <你的组件 />
    </RecoilRoot>
  );
}

atom(定义数据)

一个 atom 代表一个状态atom 可在任意组件中进行读写。读取atom 值的组件隐式订阅了该atom,因此任何atom 的更新都将致使使用对应atom 的组件重新渲染

接下来,在store/index.js中添加如下代码

javascript
import { atom } from "recoil";
export const textState = atom({
	key: "textState", // unique ID (with respect to other atoms/selectors)
	default: "", // default value (aka initial value)
});

useRecoilState(类似useState)

useRecoilState可以把它当作useState使用,它接收一个atom state,然后返回一个[state,setState],类似:

javascript
const [text, setText] = useRecoilState(textState);

components/TextInput.js中添加如下代码:

javascript
import { useRecoilState } from "recoil";
import { textState } from "../store";
export default function TextInput() {
	const [text, setText] = useRecoilState(textState);

	const onChange = (e) => {
		setText(e.target.value);
	};

	return (
		<div>
			<input type="text" onChange={onChange} />
			<br />
			Echo: {text}
		</div>
	);
}

然后在App组件中引用TextInput组件

javascript
import TextInput from "./components/TextInput";
import { RecoilRoot } from "recoil";

export default function App() {
	return (
		<RecoilRoot>
			<TextInput/>
		</RecoilRoot>
	);
}

然后我们对input框进行输入的时候,Echo也会出现对应的值,我们就初步完成了公共状态的读和写!使用起来是不是很简单?

selector(派生)

仅仅靠这些还不够,有时候我们想基于一个状态的派生出其他的状态,那么我们可以使用recoil给我们提供的selector,这个有点像Vue中的computed,或者有点像react中的useMemo。一起来看看吧

store/index.js中添加如下代码:

javascript
import { atom, selector } from "recoil";
export const charCountState = selector({
	key: "charCountState", // unique ID (with respect to other atoms/selectors)
	get: ({ get }) => {
		const text = get(textState);
		// 返回字符串的长度
		return text.length;
	},
});

这里在定义selector的时候只设置了get而没有设置set,因此这个selector是只读的,小菜鸟作者不建议设置set,如果你想设置,可以参考官网~

useRecoilValue(读取状态值)

useRecoilValue(state)可以返回给定Recoil state的值,当你只是读取数据的时候就可以使用它,使用此hook 会使组件隐式地订阅给定的state,我们利用它可以来读取刚才由selector派生的值

components/CharCount.js中添加如下代码:

javascript
import { useRecoilValue } from "recoil";
import { charCountState } from "../store";
export default function CharCount() {
	const count = useRecoilValue(charCountState);
	return <>Char Count: {count}</>;
}

App组件中引用这个组件:

javascript
import TextInput from "./components/TextInput";
import CharCount from "./components/CharCount";
import { RecoilRoot } from "recoil";

export default function App() {
	return (
		<RecoilRoot>
			<TextInput/>
      		<CharCount/>
		</RecoilRoot>
	);
}

接下来我们在input框输入数据,可以看到Echo会有相应的数据,并且Char Count会输出数据(字符串)的长度,OK~你大致学会了Recoil的核心API是怎样使用的。接下来我还会再介绍一个API

useSetRecoilState(修改状态)

useSetRecoilState 可以仅获取写函数,当你只想改变数据的时候可以使用它,它有一个特点是数据流的变化不会导致组件重新渲染,因为 useSetRecoilState 仅写不读

我们可以稍微修改一下TextInput组件,让它只是更改数据,因此我们可以在components/TextInput.js添加如下代码:

javascript
import { useSetRecoilState } from "recoil";
import { textState } from "../store";
export default function TextInput() {
	const setText = useSetRecoilState(textState);

	const onChange = (e) => {
		setText(e.target.value);
	};

	return (
		<div>
			<input type="text" onChange={onChange} />
			<br />
		</div>
	);
}

当我们在input框输入的时候,就可以看到效果啦

结语

小菜鸟作者只是写了一些DEMO和常用的的API,更多的还是见Recoil官网:Recoil🤭

Released under the MIT License.