反冲有没有办法在原子状态改变时做额外的动作?
recoil is there a way to do additional actions when the atom state changes?
我将主题状态作为后坐力的原子来管理。
如果用户通过ui改变了主题,相应的原子状态也会改变。
我想将这里更改的主题值保存到localstorage。
为此,我们需要知道该状态何时发生变化。
当然可以在调用相应的atom状态变化之前加上localstorage存储代码,但是如果atom用在很多地方,效率就太低了
此时我应该使用选择器吗?但是,由于主题是单一状态,因此ui将其作为派生状态来扩展状态更改逻辑并不明智。
如果您知道,我们将不胜感激。
example code
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { RecoilRoot, atom, useRecoilState } from "recoil";
type ThemeItem = "light" | "dark";
// : I want to do some extra work when this state changes (ex: Save the changed state to localStorage)
const themeState = atom<ThemeItem>({
key: "themeState",
default: "light",
});
function App() {
const [theme, setTheme] = useRecoilState(themeState);
function handleTheme(theme: ThemeItem) {
return () => setTheme(theme);
}
return (
<>
<h3>{theme}</h3>
<button onClick={handleTheme("light")}>light</button>
<button onClick={handleTheme("dark")}>dark</button>
</>
);
}
ReactDOM.render(
<StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);
我之前解决这个问题的方法是实现一个 ThemeProvider
(或者你想给它起的任何名字),然后使用 useEffect
从 [=13= 存储和加载值]:
import { StrictMode, useEffect } from "react";
import ReactDOM from "react-dom";
import { RecoilRoot, atom, useRecoilState } from "recoil";
type ThemeItem = "light" | "dark";
// : I want to do some extra work when this state changes (ex: Save the changed state to localStorage)
const themeState = atom<ThemeItem>({
key: "themeState",
default: "light",
});
function ThemeProvider() {
const [theme, setTheme] = useRecoilState(themeState);
useEffect(() => {
// Save theme in localStorage on change
localStorage.setItem('theme', theme);
}, [theme]);
useEffect(() => {
// Load theme from localStorage on mount
if (!localStorage.getItem('theme')) return;
setTheme(localStorage.getItem('theme') as ThemeItem);
}, []);
}
function App() {
const [theme, setTheme] = useRecoilState(themeState);
function handleTheme(theme: ThemeItem) {
return () => setTheme(theme);
}
return (
<>
<h3>{theme}</h3>
<button onClick={handleTheme("light")}>light</button>
<button onClick={handleTheme("dark")}>dark</button>
</>
);
}
ReactDOM.render(
<StrictMode>
<RecoilRoot>
<ThemeProvider />
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);
我将主题状态作为后坐力的原子来管理。
如果用户通过ui改变了主题,相应的原子状态也会改变。
我想将这里更改的主题值保存到localstorage。 为此,我们需要知道该状态何时发生变化。
当然可以在调用相应的atom状态变化之前加上localstorage存储代码,但是如果atom用在很多地方,效率就太低了
此时我应该使用选择器吗?但是,由于主题是单一状态,因此ui将其作为派生状态来扩展状态更改逻辑并不明智。
如果您知道,我们将不胜感激。
example code
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { RecoilRoot, atom, useRecoilState } from "recoil";
type ThemeItem = "light" | "dark";
// : I want to do some extra work when this state changes (ex: Save the changed state to localStorage)
const themeState = atom<ThemeItem>({
key: "themeState",
default: "light",
});
function App() {
const [theme, setTheme] = useRecoilState(themeState);
function handleTheme(theme: ThemeItem) {
return () => setTheme(theme);
}
return (
<>
<h3>{theme}</h3>
<button onClick={handleTheme("light")}>light</button>
<button onClick={handleTheme("dark")}>dark</button>
</>
);
}
ReactDOM.render(
<StrictMode>
<RecoilRoot>
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);
我之前解决这个问题的方法是实现一个 ThemeProvider
(或者你想给它起的任何名字),然后使用 useEffect
从 [=13= 存储和加载值]:
import { StrictMode, useEffect } from "react";
import ReactDOM from "react-dom";
import { RecoilRoot, atom, useRecoilState } from "recoil";
type ThemeItem = "light" | "dark";
// : I want to do some extra work when this state changes (ex: Save the changed state to localStorage)
const themeState = atom<ThemeItem>({
key: "themeState",
default: "light",
});
function ThemeProvider() {
const [theme, setTheme] = useRecoilState(themeState);
useEffect(() => {
// Save theme in localStorage on change
localStorage.setItem('theme', theme);
}, [theme]);
useEffect(() => {
// Load theme from localStorage on mount
if (!localStorage.getItem('theme')) return;
setTheme(localStorage.getItem('theme') as ThemeItem);
}, []);
}
function App() {
const [theme, setTheme] = useRecoilState(themeState);
function handleTheme(theme: ThemeItem) {
return () => setTheme(theme);
}
return (
<>
<h3>{theme}</h3>
<button onClick={handleTheme("light")}>light</button>
<button onClick={handleTheme("dark")}>dark</button>
</>
);
}
ReactDOM.render(
<StrictMode>
<RecoilRoot>
<ThemeProvider />
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);