React Basic
Re-Render
- 時機:
- 只要 component 的
state改變就會觸發 re-render - 當 component re-render 的時候,預設 child component 也會 re-render
- 只要 component 的
資訊
在進行效能優化時,除了 memo() 之外,可參考 Before You Memo
useEffect
延伸閱讀:
- 對於 React 來說所有的 function component 都是 pure function,應該只用來處理
props和state,最後回傳一個 JSX - React 的 side-effects 通常用於「跳出」React 程式碼並與某些外部系統同步。包括瀏覽器 API、第三方小工具、網路...等
useEffect預設會在每次 render 執行
Dependency Array
- 讓
useEffect只會在陣列內容變更時被執行,節省效能
import { useEffect } from "react";
function App() {
const [counter, setCounter] = useState(0);
useEffect(() => {
// useEffect 沒有 dependency array
// 每次 render 都會觸發
console.log("Render");
});
useEffect(() => {
// useEffect 的 dependency array 沒有使用到任何相依的 states 或 props
// 因此只在第一次 render 觸發
console.log("Init");
}, []);
useEffect(() => {
// useEffect 的 dependency array 有 counter
// 因此只在 counter 變動時觸發
console.log(`Counter: ${counter}`);
}, [counter]);
return (
<div>
<p>{counter}</p>
<button onClick={() => setCounter(counter + 1)}>-</button>
<button onClick={() => setCounter(counter - 1)}>+</button>
</div>
);
}
Cleanup Function
- Cleanup Function 會在下一次的
useEffect執行前執行 - 讓 component unmount 時執行需要 cleanup 的行為,例如:websocket 連線、clearInterval ...等等
import React, { useState, useEffect } from "react";
function App() {
const [counter, setCounter] = useState(0);
console.log("Execute");
useEffect(() => {
console.log(`Counter: ${counter}`);
return () => {
console.log(`Cleanup: ${counter}`);
};
});
return (
<div>
{console.log("Render")}
<p>{counter}</p>
<button onClick={() => setCounter(counter + 1)}>-</button>
<button onClick={() => setCounter(counter - 1)}>+</button>
</div>
);
}
# 第一次 Render
Execute
Render
Counter 0
# 元件更新
Execute
Render
Cleanup 0 // 上一次 useEffect 取得的值
Counter 1 // 本次執行的 useEffect 取得的值
# 元件 unmount 時
Cleanup 1