Norman's Note 諾曼筆記

Norman's Note 諾曼筆記

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

  1. 可以在 certain condition 去 render component,那它會每次都 mount 和 unmount,可以在 mount/unmount 的時刻做特定事情
  2. 也可以總是 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 筆記

input e.target.value 的 bug

問題範例

原因

由於 React v16 以前(包含)把所有 events 註冊在 document,所以共用 onChange 裡面吃到的參數 e,當你用 setState 傳 callback 的時候就會出問題,原因是 callback 執行時 e 已經不是原本的 e 了(非同步)

https://reactjs.org/docs/events.html

解法

為什麼要在 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

forward-ref

https://normanlin.net/programming/forward-ref