[React] 利用key強迫re-render

張庭瑋
4 min readOct 14, 2020

--

今天朋友用useEffect模擬componentDidMount和componentWillUnmount時

遇到了些問題而跑來跟我分享,覺得頗有收獲,在此紀錄一下

首先先來看code

邏輯就是點了按鈕後Y會消滅,生成X,反之亦然

然後使用useEffect

在元件生成時執行console.log(“mount:”, current)(模擬componentDidMount

在元件消滅前執行console.log(“unmount:”, current)(模擬componentWillUnmount

預期是mount和unmount交互列印

點了之後卻發現console欄不論怎麼點擊按鈕只顯示mount: Y

以下就來看看怎麼解決這個問題

1.將props放入第二參數

這裡用了useRef是為了關掉警告,如果普通大概會這樣寫

const SideEffect = ({ text }) => {  useEffect(() => {    console.log("mount:", text);    return () => console.log("unmount:", text);  }, []);  return null;};

然後有開eslint的就會接到警告了

React Hook useEffect has a missing dependency: 'text'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

這裡就把text加進useEffect第二參數的陣列中

表示text發生變化時re-render

const SideEffect = ({ text }) => {  useEffect(() => {    console.log("mount:", text);    return () => console.log("unmount:", text);  }, [text]);  return null;};

這時會有人說:啊你不是說要模擬componentDidMount和componentWillUnmount嗎?這兩個函數能帶參數嗎?

於是接下來不改動SideEffect元件,而只在App中更改

原本預期的是

console.log(“mount:”, current)console.log(“unmount:”, current)

交互列印

然而這件事並沒有發生,這其實就代表元件沒有re-render,而是更新資料而已,原因是

<>  <h1>X</h1>  <SideEffect text="X" /></>

這兩個元件

<>  <h1>Y</h1>  <SideEffect text="Y" /></>

在React眼裡都是長這樣

fragment   
h1
SideEffect ()

既然是同樣的東西,那麼只更新資料自然是比較好的選擇

2.將原本的三元運算子以&&改寫

{!value && (  <>    <h1>X</h1>    <SideEffect text="X" />  </>) }{value && (  <>    <h1>Y</h1>    <SideEffect text="Y" />  </>) }

這麼寫的話component tree會有兩種可能

// 第1種
fragment
h1
SideEffect (X)
false
// 第2種
false
fragment
h1
SideEffect (Y)

由於結構完全不同,這裡就會re-render

當然又會有人說:這樣寫好醜,原本的三元運算子不行嗎?

3.跟React標示這是不同的元件

上面有提到,原本的寫法在component tree中看起來永遠是這樣子

fragment   
h1
SideEffect ()

因此要用別的方式跟React表示這兩個是不同的元件,而不是同一個元件,React就不會用更新資料的方式處理

<Fragment key="X">  <h1>X</h1>  <SideEffect text="X" /></Fragment>

也就是加上key就可以解決了

這裡要注意如果要把<> </>加上key就要把Fragment插進來並寫出來

成果:

Sign up to discover human stories that deepen your understanding of the world.

--

--

No responses yet

Write a response