[React] React trivia
React 優缺點/特色?
- React is declarative(宣告式),它關注的是你要做什麼,而不是如何做。使用者只需要使用 React 提供的 api 做 state, data 的更改,與 DOM 相關的操作 React 會在底層幫忙處理好。這樣的優點是讓 DOM 為人詬病的 performance 問題(主要因為 reflow, repaint 很耗費性能),可以被 react 用 virtual-DOM 給解決。
- React 讓我們可以建立能被重複使用的組件,來增加程式碼可度性、重複性,減少 debug 時間。
- React 是one way data flow,代表單一方向的資料流動,減少 debug 時間跟錯誤。
- 大量的 npm package/社群
Keys 在 react 中代表什麼?
key 可以幫助 React 跟蹤循環創建列表中的虛擬 DOM 元素,瞭解哪些元素已更改、添加或刪除。
每個綁定 key 的虛擬 DOM 元素,在附近的元素之間都是獨一無二的。在 React 的 reconciliation 過程中,比較新的虛擬 DOM 樹與上一個 virtual-DOM 樹之間的差異,並更改到頁面中。key 使 React 處理列表中虛擬 DOM 時更加高效,因爲 React 可以使用虛擬 DOM 上的 key 屬性,快速瞭解元素是新的、需要刪除的,還是修改過的。如果沒有 key, React 就不知道列表中虛擬 DOM 元素與頁面中的哪個元素相對應。
https://mp.weixin.qq.com/s/lAQP3wNVuHpp-mt_RAqK1A
controlled components vs uncontrolled components in React?
controlled components
:指的透過 onChange 或是其他 callback 方式,把 value 儲存在 parents components,被 parents components 所”控制“的 components.
<input type="text" value={value} onChange={handleChange} />
uncontrolled components
:指的儲存自己的 value,而必須透過ref
來獲取裡面的 value 的 component,通常用於與其他非 react code 合作時.
<input type="text" defaultValue="foo" ref={inputRef} />
https://reactjs.org/docs/uncontrolled-components.html
React element vs components?
React element 是一個用來形容 components 或是 DOM node 的 Js object。
// React element
{
type: 'button',
props: {
className: 'button button-blue',
children: {
type: 'b',
props: {
children: 'OK!'
}
}
}
}
<button class='button button-blue'>
<b>
OK!
</b>
</button>
React component 指的是 functions/classes 有 props 傳進來當作 input,然後回傳 elements 當作 output。
https://zh-hant.reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html
Error boundary 錯誤邊界
用途:避免當一個組件壞掉時,導致全部的組件都壞變,而無法捕捉這些錯誤。Error boundary 會去抓 runtime Error
,亦即沒被編譯器找到 但是在運行中強迫被中止的錯誤(ex, window.printme(),而 printme()不存在)。
錯誤邊界有兩個作用
- 如果發生錯誤,顯示回退 UI
- 記錄錯誤
https://zh-hant.reactjs.org/docs/error-boundaries.html#how-about-event-handlers
Props vs State
props 是被傳遞進 component(類似於 function 的參數),而 state 是在 component 內部被管理(類似於在 function 中宣告中的變數)。 此外,props 應該要是 immutable 的。
Batching
用途:避免不必要的 rerender,react 會等到全部的 event handler 都跑完,然後才會跑 batch rerender
function Parent() {
let [count, setCount] = useState(0);
return (
<div onClick={() => setCount(count + 1)}>
Parent clicked {count} times
<Child />
</div>
);
}
function Child() {
let [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Child clicked {count} times
</button>
);
}
without batching
//Entering React's browser click event handler
Child (onClick)
- setState
- re-render Child // 😞 unnecessary
Parent (onClick)
- setState
- re-render Parent
- re-render Child
//Exit
with batching
// Entering React's browser click event handler ***
Child (onClick)
- setState
Parent (onClick)
- setState
Processing state updates
- re-render Parent
- re-render Child
//Exit
Ex.
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
}
function handleClick() {
increment();
increment();
increment();
// these would just be three setCount(1) calls.
}
handleClick();
//count => 1
Fix:
const [count, setCount] = useState(0);
function increment() {
setCount((prev) => prev + 1);
}
function handleClick() {
increment();
increment();
increment();
//React would put the updater functions in a queue, and later run them in sequence, resulting in a re-render with count set to 3.
}
//count => 3
React one-way data flow/ one-way data binding
- 資料是從 parent 透過 props 往下傳到 child
- child 有兩種選擇 1. 使用該 props 2. 繼續往下傳到子 component
one-way data flow 缺點
- props drilling
解決方法:
- Redux => 把資料都放到一個統一的 store
資源: https://tkssharma.gitbook.io/react-training/day-01/react-js-3-principles/one-way-data-flow
Share data between tabs when using react & redux ?
Redux 只存在個別 tab 裡,所以如果要在各個 tab 中使用共同的資料的話,有以下幾個方法:
- 使用 redux-persist
- 使用 localStorage
- 使用 react-router 把資料放在 pathname 裡面
useLayoutEffect vs useEffect
效果類似 useEffect,差別是 useLayoutEffect 會在,state 被更改然後 DOM 變更後同步被調用。useEffect 則是在 state 被更改,DOM 變更,畫面 paint 在 browser 裡後才非同步的調用。 代表 useLayoutEffect 會永遠比 useEffect 早被執行,且因為在畫面被 paint 之前就同步調用,所以 useLayoutEffect 很適合用來處理 DOM 操作、頁面閃爍等情況。
實踐 useState, useEffect?
https://github.com/brickspert/blog/issues/26
Synthetic event 合成事件
attach synthetic event at root
why?
https://reactjs.org/blog/2020/08/10/react-v17-rc.html
TL;DR
避免遇到 project 中有其他原生的 document 操作時,在 document 上的操作會互相衝突,原生的 document event handler 會引響到 React 本身設定在 document 的合成事件,所以 react17 把合成事件改在 root 上
example
https://www.bigbinary.com/blog/react-17-delegates-events-to-root-instead-of-document
Higher order function vs Higher order component
HOF: A function that takes a function as an argument, or returns a function as a result
ex, Array.prototype.map();
HOC: A function that takes a component as an argument, or returns a component as a result
const EnhancedComponent = higherOrderComponent(WrappedComponent);
React doc HOC 介紹:https://zh-hant.reactjs.org/docs/higher-order-components.html
React pure component
import { PureComponent } from "react";
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent is a subclass of Component and supports all the Component APIs. Extending PureComponent is equivalent to defining a custom shouldComponentUpdate method that shallowly compares props and state.
React doc 建議新程式碼使用 function component 來取代過去的 class component。
在 functional component 中可以使用 React.memo() 來達到跟 Pure Component 一樣的效果。
Resources: https://beta.reactjs.org/reference/react/PureComponent
React vs other framework
https://www.builder.io/blog/reactivity-across-frameworks
Resources:
https://overreacted.io/react-as-a-ui-runtime/#batching https://juejin.cn/post/6844903857135304718 https://zh-hant.reactjs.org/docs/faq-state.html#what-is-the-difference-between-state-and-props