昨天介紹到如何在我們的元件中 read / write 共享的狀態,像是 useState 一樣,我們呼叫 useRecoilState。
const [count, setCount] = useRecoilState(counterState);
但其實官方這裡有3組對應的 API 分別是
1.useRecoilState(state)
2.useRecoilValue(state)
3.useSetRecoilState(state)
就如同 useState 一般,不過裡面放入的預設值是 Recoil 的 atom 或 selector,並且我們會得到 state 跟 setter function。當使用這個 hook 時,該元件會被訂閱,只要那個 shared state 有更新時,這個元件會被重新渲染(re-render)。
這個 setter function 裡面的參數可以放入一個 新的值 或 updater function。
setCount(99)
setCount( prevCount => (prevCount + 1) )
import { useRecoilState } from 'recoil';
const Counter = () => {
const [count, setCount] = useRecoilState(counterState);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<h2>{count}</h2>
<button onClick={handleClick}>遞增</button>
</div>
);
}
如果你的 shared state 是唯讀的 (read-only) ,比如說像是某個 selector 透過 atom 計算出來的共享狀態 (未來會對 selector 有更多的介紹,這邊還不清楚沒關係) ,或是你只需要 shared state 但不需要 setter function 時,你可以使用 useRecoilValue。
const count = useRecoilValue(counterState);
在這裡,我們就只會拿到 shared state 而已,當使用這個 hook 時,該元件會被訂閱,只要那個 shared state 有更新時,這個元件會被重新渲染(re-render)。
如果在這邊你只想要修改共享狀態,但是你的元件或 hook 不需要讀取狀態時,可以使用useSetRecoilState 拿到 shared state 的 setter function。
const setCount = useSetRecoilState(counterState);
在這裡,我們就只會拿到 shared state 的 setter function 而已,當使用這個 hook 時,該元件不被訂閱,所以那個 shared state 有更新時,這個元件不會被重新渲染。
// Recoiljs 官網範例
const namesState = atom({
key: 'namesState',
default: ['Ella', 'Chris', 'Paul'],
});
function FormContent({setNamesState}) {
const [name, setName] = useState('');
return (
<>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
<button onClick={() => setNamesState(names => [...names, name])}>Add Name</button>
</>
)}
// 這個元件只會在 mounted 時,被渲染一次
function Form() {
const setNamesState = useSetRecoilState(namesState);
return <FormContent setNamesState={setNamesState} />;
}
這兩個 hook 唯一不同之處在於:
1.useRecoilState 會訂閱使用它的元件,當該 shared state 改變時,使用這個 hook 的元件會被重新渲染 (re-render)
2.useSetRecoilState 則不會訂閱使用它的元件,當該 shared state 改變時,使用這個 hook 的元件不會被重新渲染 (re-render)