Atom基础 #
什么是 Atom? #
Atom 是 Recoil 中最小的状态单元,它代表一个可订阅、可修改的状态。可以把 Atom 想象成一个全局的 useState,但可以被任何组件访问。
text
┌─────────────────────────────────────────┐
│ Atom │
├─────────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Component│ │Component│ │Component│ │
│ │ A │ │ B │ │ C │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └────────────┼────────────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ Atom │ │
│ │ (状态源) │ │
│ └───────────┘ │
└─────────────────────────────────────────┘
创建 Atom #
基本语法 #
jsx
import { atom } from 'recoil';
const myState = atom({
key: 'myState',
default: initialValue,
});
参数说明 #
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
key |
string | 是 | 唯一标识符,全局唯一 |
default |
any | 是 | 默认值,可以是任意类型 |
创建不同类型的 Atom #
jsx
import { atom } from 'recoil';
const countState = atom({
key: 'countState',
default: 0,
});
const textState = atom({
key: 'textState',
default: 'Hello',
});
const userState = atom({
key: 'userState',
default: {
id: 1,
name: 'John',
email: 'john@example.com',
},
});
const todoListState = atom({
key: 'todoListState',
default: [],
});
const isLoggedInState = atom({
key: 'isLoggedInState',
default: false,
});
使用 Atom #
useRecoilState - 读写状态 #
useRecoilState 类似于 useState,返回一个数组:[value, setValue]。
jsx
import { useRecoilState } from 'recoil';
function Counter() {
const [count, setCount] = useRecoilState(countState);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
);
}
useRecoilValue - 只读状态 #
当组件只需要读取状态,不需要修改时,使用 useRecoilValue:
jsx
import { useRecoilValue } from 'recoil';
function CountDisplay() {
const count = useRecoilValue(countState);
return <p>Current count: {count}</p>;
}
useSetRecoilState - 只写状态 #
当组件只需要修改状态,不需要读取时,使用 useSetRecoilState:
jsx
import { useSetRecoilState } from 'recoil';
function IncrementButton() {
const setCount = useSetRecoilState(countState);
return (
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
);
}
useResetRecoilState - 重置状态 #
重置 Atom 到默认值:
jsx
import { useResetRecoilState } from 'recoil';
function ResetButton() {
const resetCount = useResetRecoilState(countState);
return <button onClick={resetCount}>Reset</button>;
}
更新状态 #
直接设置值 #
jsx
const [count, setCount] = useRecoilState(countState);
setCount(10);
使用函数更新 #
jsx
setCount(prev => prev + 1);
更新对象状态 #
jsx
const [user, setUser] = useRecoilState(userState);
setUser({
...user,
name: 'Jane',
});
setUser(prev => ({
...prev,
email: 'jane@example.com',
}));
更新数组状态 #
jsx
const [todos, setTodos] = useRecoilState(todoListState);
setTodos([...todos, newTodo]);
setTodos(todos.filter(todo => todo.id !== id));
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: true } : todo
));
实战示例:Todo List #
jsx
import { atom, useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
const todoListState = atom({
key: 'todoListState',
default: [],
});
const todoFilterState = atom({
key: 'todoFilterState',
default: 'all',
});
function TodoList() {
const [todos, setTodos] = useRecoilState(todoListState);
const addTodo = (text) => {
setTodos([
...todos,
{
id: Date.now(),
text,
completed: false,
},
]);
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div>
<TodoInput onAdd={addTodo} />
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
{todo.text}
</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
function TodoInput({ onAdd }) {
const [text, setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
onAdd(text);
setText('');
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Add todo..."
/>
<button type="submit">Add</button>
</form>
);
}
Atom 的默认值 #
静态默认值 #
jsx
const countState = atom({
key: 'countState',
default: 0,
});
对象默认值 #
jsx
const userState = atom({
key: 'userState',
default: {
name: '',
email: '',
age: 0,
},
});
使用另一个 Atom 作为默认值 #
jsx
const baseCountState = atom({
key: 'baseCountState',
default: 10,
});
const countState = atom({
key: 'countState',
default: baseCountState,
});
Atom Effects #
Atom Effects 是在 Atom 创建时执行的副作用函数:
jsx
const countState = atom({
key: 'countState',
default: 0,
effects: [
({ onSet }) => {
onSet((newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
},
({ setSelf, onSet }) => {
const savedValue = localStorage.getItem('count');
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue) => {
localStorage.setItem('count', JSON.stringify(newValue));
});
},
],
});
Effects API #
jsx
effects: [
({
node,
trigger,
setSelf,
resetSelf,
onSet,
getPromise,
getLoadable,
getInfo_UNSTABLE,
}) => {
},
]
| 方法 | 说明 |
|---|---|
setSelf |
设置初始值 |
resetSelf |
重置到默认值 |
onSet |
监听值变化 |
getPromise |
异步获取其他状态 |
getLoadable |
同步获取其他状态 |
持久化示例 #
jsx
const localStorageEffect = (key) => ({ setSelf, onSet }) => {
const savedValue = localStorage.getItem(key);
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
});
};
const todoListState = atom({
key: 'todoListState',
default: [],
effects: [
localStorageEffect('todo_list'),
],
});
性能优化 #
选择合适的 Hook #
jsx
function OptimizedComponent() {
const setCount = useSetRecoilState(countState);
return <button onClick={() => setCount(c => c + 1)}>+</button>;
}
使用 useSetRecoilState 而不是 useRecoilState,组件不会在 count 变化时重渲染。
避免不必要的订阅 #
jsx
function UserName() {
const user = useRecoilValue(userState);
return <span>{user.name}</span>;
}
function UserEmail() {
const user = useRecoilValue(userState);
return <span>{user.email}</span>;
}
如果 name 和 email 经常独立变化,应该拆分为独立的 Atom:
jsx
const userNameState = atom({ key: 'userName', default: '' });
const userEmailState = atom({ key: 'userEmail', default: '' });
总结 #
本章学习了 Atom 的基础用法:
| Hook | 用途 |
|---|---|
useRecoilState |
读写状态 |
useRecoilValue |
只读状态 |
useSetRecoilState |
只写状态 |
useResetRecoilState |
重置状态 |
下一步,让我们学习 Atom配置,深入了解 Atom 的高级配置选项。
最后更新:2026-03-28