useSetRecoilState #
什么是 useSetRecoilState? #
useSetRecoilState 是一个只写 Hook,用于获取设置 Recoil 状态的函数。当组件只需要修改状态而不需要读取时,使用这个 Hook 可以避免不必要的重渲染。
jsx
const setValue = useSetRecoilState(state);
基本用法 #
设置状态 #
jsx
import { atom, useSetRecoilState } from 'recoil';
const countState = atom({
key: 'countState',
default: 0,
});
function IncrementButton() {
const setCount = useSetRecoilState(countState);
return (
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
);
}
重置状态 #
jsx
function ResetButton() {
const setCount = useSetRecoilState(countState);
return (
<button onClick={() => setCount(0)}>
Reset
</button>
);
}
性能优势 #
避免订阅状态变化 #
使用 useSetRecoilState 的组件不会在状态变化时重渲染:
jsx
function OptimizedButton() {
const setCount = useSetRecoilState(countState);
console.log('This only logs once on mount');
return (
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
);
}
对比使用 useRecoilState:
jsx
function LessOptimizedButton() {
const [count, setCount] = useRecoilState(countState);
console.log('This logs on every count change');
return (
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
);
}
更新方式 #
直接设置值 #
jsx
const setCount = useSetRecoilState(countState);
setCount(10);
setCount(0);
使用函数更新 #
jsx
setCount(prev => prev + 1);
setCount(prev => prev * 2);
更新对象 #
jsx
const setUser = useSetRecoilState(userState);
setUser({ name: 'John', email: 'john@example.com' });
setUser(prev => ({ ...prev, name: 'Jane' }));
更新数组 #
jsx
const setTodos = useSetRecoilState(todoListState);
setTodos(prev => [...prev, newTodo]);
setTodos(prev => prev.filter(todo => todo.id !== id));
实战示例:表单提交 #
jsx
import { atom, useSetRecoilState, useRecoilValue } from 'recoil';
const formState = atom({
key: 'formState',
default: {
username: '',
email: '',
},
});
const submittedState = atom({
key: 'submittedState',
default: false,
});
function SubmitButton() {
const setSubmitted = useSetRecoilState(submittedState);
const setForm = useSetRecoilState(formState);
const handleSubmit = () => {
setSubmitted(true);
setForm({ username: '', email: '' });
};
return (
<button onClick={handleSubmit}>
Submit
</button>
);
}
实战示例:通知系统 #
jsx
import { atom, useSetRecoilState } from 'recoil';
const notificationsState = atom({
key: 'notifications',
default: [],
});
function useNotifications() {
const setNotifications = useSetRecoilState(notificationsState);
const addNotification = (message, type = 'info') => {
const id = Date.now();
setNotifications(prev => [
...prev,
{ id, message, type, timestamp: Date.now() },
]);
setTimeout(() => {
removeNotification(id);
}, 5000);
};
const removeNotification = (id) => {
setNotifications(prev => prev.filter(n => n.id !== id));
};
const clearAll = () => {
setNotifications([]);
};
return { addNotification, removeNotification, clearAll };
}
function NotificationButtons() {
const { addNotification, clearAll } = useNotifications();
return (
<div>
<button onClick={() => addNotification('Success!', 'success')}>
Add Success
</button>
<button onClick={() => addNotification('Error!', 'error')}>
Add Error
</button>
<button onClick={clearAll}>
Clear All
</button>
</div>
);
}
实战示例:主题切换 #
jsx
import { atom, useSetRecoilState, useRecoilValue } from 'recoil';
const themeState = atom({
key: 'theme',
default: 'light',
});
function ThemeToggle() {
const setTheme = useSetRecoilState(themeState);
const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};
return (
<button onClick={toggleTheme}>
Toggle Theme
</button>
);
}
function ThemeDisplay() {
const theme = useRecoilValue(themeState);
return <div>Current theme: {theme}</div>;
}
实战示例:购物车操作 #
jsx
import { atom, useSetRecoilState } from 'recoil';
const cartState = atom({
key: 'cart',
default: [],
});
function ProductCard({ product }) {
const setCart = useSetRecoilState(cartState);
const addToCart = () => {
setCart(prev => {
const existing = prev.find(item => item.id === product.id);
if (existing) {
return prev.map(item =>
item.id === product.id
? { ...item, quantity: item.quantity + 1 }
: item
);
}
return [...prev, { ...product, quantity: 1 }];
});
};
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={addToCart}>Add to Cart</button>
</div>
);
}
function ClearCartButton() {
const setCart = useSetRecoilState(cartState);
return (
<button onClick={() => setCart([])}>
Clear Cart
</button>
);
}
与 useCallback 结合 #
jsx
import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
function OptimizedComponent() {
const setCount = useSetRecoilState(countState);
const increment = useCallback(() => {
setCount(c => c + 1);
}, [setCount]);
const decrement = useCallback(() => {
setCount(c => c - 1);
}, [setCount]);
const reset = useCallback(() => {
setCount(0);
}, [setCount]);
return (
<div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
与自定义 Hook 结合 #
jsx
function useCounterActions() {
const setCount = useSetRecoilState(countState);
const increment = useCallback(() => {
setCount(c => c + 1);
}, [setCount]);
const decrement = useCallback(() => {
setCount(c => c - 1);
}, [setCount]);
const reset = useCallback(() => {
setCount(0);
}, [setCount]);
const set = useCallback((value) => {
setCount(value);
}, [setCount]);
return { increment, decrement, reset, set };
}
function CounterControls() {
const { increment, decrement, reset } = useCounterActions();
return (
<div>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
TypeScript 支持 #
tsx
import { atom, useSetRecoilState } from 'recoil';
interface User {
id: number;
name: string;
email: string;
}
const userState = atom<User | null>({
key: 'userState',
default: null,
});
function LoginButton() {
const setUser = useSetRecoilState(userState);
const handleLogin = async () => {
const user = await login();
setUser(user);
};
return <button onClick={handleLogin}>Login</button>;
}
完整示例:用户认证 #
jsx
import { atom, useSetRecoilState, useRecoilValue } from 'recoil';
const authState = atom({
key: 'auth',
default: {
isLoggedIn: false,
user: null,
token: null,
},
});
function useAuth() {
const setAuth = useSetRecoilState(authState);
const login = async (credentials) => {
try {
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify(credentials),
});
const data = await response.json();
setAuth({
isLoggedIn: true,
user: data.user,
token: data.token,
});
return { success: true };
} catch (error) {
return { success: false, error };
}
};
const logout = () => {
setAuth({
isLoggedIn: false,
user: null,
token: null,
});
};
return { login, logout };
}
function LoginButton() {
const { login } = useAuth();
return (
<button onClick={() => login({ username: 'user', password: 'pass' })}>
Login
</button>
);
}
function LogoutButton() {
const { logout } = useAuth();
return <button onClick={logout}>Logout</button>;
}
function AuthStatus() {
const auth = useRecoilValue(authState);
return (
<div>
{auth.isLoggedIn ? (
<span>Logged in as {auth.user.name}</span>
) : (
<span>Not logged in</span>
)}
</div>
);
}
总结 #
useSetRecoilState 的核心要点:
| 特点 | 说明 |
|---|---|
| 只写 | 只能修改状态,不能读取 |
| 无订阅 | 状态变化不会触发重渲染 |
| 性能 | 适用于只需要修改状态的组件 |
| 返回值 | 返回设置函数 |
下一步,让我们学习 useResetRecoilState,了解重置状态的 Hook。
最后更新:2026-03-28