lifecycle methods 如何對照到 Hooks?
constructor
:Function component 不需要使用 constructor 來初始化 state,而是使用 useState。如果運算初始狀態會花費太多力氣,你可以嘗試傳遞一個 function 給 useState。
getDerivedStateFromProps
:這個方法會在 call render method 之前運行,在初始的 mounting 以及接下來的更新都會觸發,會 return 一個物件來更新狀態,實作的情境不多,通常是當狀態需要隨著 props 中的改變而改變的情境。
在 Hook 當中,會使用他的情境也是非常稀少,以下是替代 getDerivedStateFromProps
的實作案例。你可以在 rendering 進行的時候更新狀態,React 會在結束第一次 render 之後,立刻使用更新過的狀態重新跑一次元件,藉此節省效能。(案例原文在此 https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops)
// 以下是個偵測使用者是否正在往下滑動頁面的功能
function ScrollView({row}) {
const [isScrollingDown, setIsScrollingDown] = useState(false);
const [prevRow, setPrevRow] = useState(null);
if (row !== prevRow) {
setIsScrollingDown(prevRow !== null && row > prevRow);
// 我們把 row 的狀態儲存在 state 裡,所以可以比較滑動的位置是否有改變
setPrevRow(row);
}
return `Scrolling down: ${isScrollingDown}`;
}
shouldComponentUpdate
:你可以把 function component 包在 React.memo 裡,來比較 props 是否改變(shallowly)。
const Button = React.memo((props) => {
// your component
});
render
: 就是 function component 的 body
componentDidMount
, componentDidUpdate
, componentWillUnmount
: useEffect 可以呈現所有這些方法的結合。
// 跟 componentDidMount + componentDidUpdate 很類似:
useEffect(() => {
document.title = `You clicked ${count} times`;
});
即使是比較稀少的情境,例如只在 updates 的時候 run effect,也可以透過 mutable ref 來手動儲存代表是否是在第一次 render 的 boolean value。
// 以下是參考 stackoverflow 上討論的寫法,非文件裡提供
// 使用 ref 來儲存 render 的次數(不使用 useState 來儲存以避免多餘的 render)
const isFirstRender = useRef(true);
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
} else {
// 如果不是首次 render,則運行以下的 code
// ....
}
});
Hooks 裡面有類似 instance variables (實例變數)的東西嗎?
useRef() 不只可以用在 DOM 上面,ref 物件是一個含有 current property 的容器,而 current 是 mutable 的,可以儲存任何 value,跟 class 裡頭的實例變數概念很像。(不過你應該要避免在 render 的時候設定 ref,比較好的地方是 event handlers 和 effect)
ref
https://reactjs.org/docs/hooks-faq.html
https://stackoverflow.com/questions/55075604/react-hooks-useeffect-only-on-update