React.js 筆記
管理狀態
如果要做 re-render 的狀態管理用 useState
,但如果不需要 re-render,可以用 useRef
Portals
ReactDOM.createPortal(child, container)
https://reactjs.org/docs/portals.html
https://codepen.io/gaearon/pen/yzMaBd
render pattern
- 可以在 certain condition 去 render component,那它會每次都 mount 和 unmount,可以在 mount/unmount 的時刻做特定事情
- 也可以總是 render,但在 child component 裡面去控制要不要 return 內容,這樣可以在 child component 做狀態處理
useEffect
裡面的 return function 執行時間點:
- 第二次 browser paint 後、第二次 useEffect 前,也就是先 clear 再做下一次 effect(所以總執行次數為 effect 次數 - 1)
- component will unmount,在 unmount 前,所以可以在 return function 用 query selector 還可以抓到畫面 ui
Portals
可以把 component render 在 parent 以外的 DOM
https://reactjs.org/docs/portals.html
筆記
useState
: 記得可以用prevState
去看上次的狀態來做改變useEffect
: 檢查 dependency 是否和上次有不一樣
a: PropTypes.arrayOf(
PropTypes.shape({
b: PropTypes.string.isRequired,
})
).isRequired,
Button.propTypes = {
appearance: PropTypes.oneOf(['primary', 'secondary'])
}
TimeSince.propTypes = {
time: PropTypes.oneOfType([
PropTypes.number,
PropTypes.instanceOf(Date)
])
}
Key Event 筆記
-
從 React 原始碼看 keyPress 與 keyDown 事件
keyDown 會在你按下任何按鍵時觸發,但是 keyPress 只會在你按下的按鍵可以產生出一個字元的時候觸發 -
React 原始碼:https://github.com/facebook/react/blob/v16.13.1/packages/react-dom/src/events/getEventKey.js#L103
-
Unicode 在 JavaScript 中的使用
\u7db2\u9801\u524d\u7aef\u8cc7\u6e90\u7ad9
-
input
value
不可以是undefined
,否則無法用 js 控制裡面的值 -
onChange
1. 需要使用者輸入 && 2. 值確實有改變,才會觸發onChange
,全選後輸入同樣的字母,因為裡面的字母沒有改變,是不會觸發的
input e.target.value
的 bug
問題範例
原因
由於 React v16 以前(包含)把所有 events 註冊在 document,所以共用 onChange 裡面吃到的參數 e
,當你用 setState 傳 callback 的時候就會出問題,原因是 callback 執行時 e
已經不是原本的 e
了(非同步)
https://reactjs.org/docs/events.html
解法
- v16:
e.persist();
- 先結構再傳
const { target } = e;
,因為就算 React 換掉 target,你還是擁有原本的 Reference - 升級至 v17 https://reactjs.org/blog/2020/08/10/react-v17-rc.html#no-event-pooling
為什麼要在 setState 傳 callback
在連續做三次、而且這三次互相相關的時候(例如 prevState + 1),由於 setState 的非同步特性,直接傳值的話,最後的結果會是錯的,你會需要拿前一次做完的值來 +1
setCount((prevState) => prevState + 1);
// 錯誤示範
setCount(x + 1) // * 3
(待確定)
另外要注意的是,如果在同一個 batched updates cycle,你的 component render (state) 會跳過中間曾經有過的值(React 為了減少 render 次數),例如:
onClick={() => setState(x)}
onFocus={() => setState(y)}
onBlur={() => setState(z)}
同一批 cycle update 完之後,才會印出最終值(如果你在 functional component 裡面 console.log 出來看的話)
https://blog.logrocket.com/simplifying-state-management-in-react-apps-with-batched-updates/
https://codesandbox.io/s/batched-update-snippet1-4wuk8?file=/src/index.js
同步、非同步、micro task (queue)
https://codesandbox.io/s/xenodochial-jepsen-iuyhn?file=/src/index.js