[ReactDoc] React Hooks - API Reference
Hooks API Reference @ React Docs
useState
useState @ React Docs - Hooks API Reference
⚠️ 特別留意:在 useState
的 set function 和 Class 中的 setState
不同,useState 的 set function 不會主動 merge,因此可以透過 { ...preObject }
的用法複製完整的物件。
functional updater:使用前一次的資料狀態
如果有需要的話,在 setCount
的函式中可以帶入 function,這個 function 可以取得前一次的資料狀態:
const [foo, setFoo] = useState(initialFoo);
setFoo((prevState) => /* do something with prevState */)
使用範例:
function Counter({ initialCount }) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount((prevCount) => prevCount + 1)}>+</button>
<button onClick={() => setCount((prevCount) => prevCount - 1)}>-</button>
</>
);
}
⚠️ 在 useEffect 或 useCallback 中善用 prevState 避免狀態依賴
若我們在 setCount
中使用的是前一次的狀態,就可以把該狀態從相依陣列(dependency array)中移除,這麼做的好處是畫面會隨時間繼續重新 render,但 useEffect 和裡面的 cleanup function 並不會每次都被叫到,像是這樣:
其他範例 如何錯誤地使用 React hooks useCallback 來保存相同的 function instance:
import React, { useState, useCallback, useRef } from 'react';
import ReactDOM from 'react-dom';
import './styles.css';
const Button = React.memo(({ handleClick }) => {
const refCount = useRef(0);
return <button onClick={handleClick}>{`button render count ${refCount.current++}`}</button>;
});
function App() {
const [isOn, setIsOn] = useState(false);
// 在 setIsOn 中帶入 prevState 可以避免把 state 或 props 放入相依陣列中
const handleClick = useCallback(() => setIsOn((isOn) => !isOn), []);
return (
<div className="App">
<h1>{isOn ? 'On' : 'Off'}</h1>
<Button handleClick={handleClick} />
</div>
);
}
const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);