iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
自我挑戰組

我與 React 的 30天系列 第 17

Day 17 為什麼要渲染我啊,那你有聽過 React.memo 嗎?

  • 分享至 

  • xImage
  •  

我們踏進 React 的世界也將近 20 天了,對於 React 渲染的機制應該也略知一二了...你說你不懂,那就讓我來解釋一下吧,我們一樣做出了 Parent.jsChild.js Component,並在 App.js 使用 useState 做一個簡單的計數器,畫面會像是這樣

// App.js
import { useState } from 'react';
import { Parent } from './Parent';
import './index.css';

function App() {
  const [count, setCount] = useState(0)
  console.log("APP 組建 渲染");

  const clickHandler = () => {
    setCount(perv => perv + 1)
  }

  return (
    <div className='border'>
      <div>
        我是在 APP.js 的 count :{ count }
      </div>
      <button onClick={clickHandler}>點我加一</button>
      <Parent item={"傳下來的東西"} />
    </div>
  );
}

export default App;

// Parent.js
import './index.css'
import { Child } from "./Child"

const Parent = ({ item }) => {
  console.log("我是Parent.js 為啥要渲染我啊");

  return (
    <div className='parent'>
      我是Parent.js
      <span className='item'>{ item }</span>
      <Child  item={item} />
    </div>
  )
}

export { Parent }
// Child.js
import './index.css'

const Child = ({ item }) => {
  console.log("我是Child.js 為啥要渲染我啊");

  return (
    <div className='child'>
      我是Child.js
      <span className='item'>{ item }</span>
    </div>
  )
}

export { Child }

但是這時悲劇就發生了,每當我在最上層的 App.js 點擊button 讓他去執行,setCount,這時大家也都知道,這個行為會呼叫,React 重新渲染 App.js 這個組件,然後這時,發現了 App.js 這個組件中,還有其他子組件,這時 react 也會去渲染這個組件,直到,沒有組件可以渲染為止,所以才會造成畫面上的這個效果

但是大家都知道老套路了,React 本人也發現了這個問題,所以 React.memo就來拯救世界了

React.memo 怎麼用?

知道這項工具知道,那我們該怎麼使用呢?
讓我們來試試看吧,其實很簡單

先讓我們思考一下,現在 App.js 會因為 useState 的狀態改變而渲染,這點沒錯
但是我們的 Parent.jsChild.js 不需要重新渲染,為什麼?

因為第一點 因為傳下來的 props 沒有改變,在我們的例子中是一個字串,"傳下來的東西"
再來就是,如果每次父層渲染都要影響子層的話,而且子層的狀態沒有改變,那為什麼要跟這渲染。

思考之後,我們就可以在我們不需要被渲染的地方加上今天的主角 memo
Parent.jsChild.js 加上這些

memo 將我們的 function 包起來

// Parent.js
import './index.css'
import { Child } from "./Child"
import { memo } from 'react';

const Parent = memo(({ item }) => {
  console.log("我是Parent.js 為啥要渲染我啊");

  return (
    <div className='parent'>
      我是Parent.js
      <span className='item'>{ item }</span>
      <Child  item={item} />
    </div>
  )
})

export { Parent }
// Child.js
import './index.css'
import { memo } from 'react';

const Child = memo(({ item }) => {
  console.log("我是Child.js 為啥要渲染我啊");

  return (
    <div className='child'>
      我是Child.js
      <span className='item'>{ item }</span>
    </div>
  )
})
// 注意你也可以這樣使用 memo
// const MemoChild = memo(Child)
// 但是注意要引出的時候要用對人 export { Child, MemoChild }
// 引入時也是一樣


export { Child }

讓我們來看看下效果吧

成功做出我們要的效果了~

React.memo,我還是比較喜歡 memo

其實這兩個東西是一樣的,只是有些人會習慣在 import 的時候,把 React 引入像是這樣

import React from 'react';

這樣你一樣可以使用 React.useState(),React.memo

但是本人我比較喜歡像是這樣,只引入自己需要的 function

import { useState, memo } from 'react';

這樣也可以很清楚知道,這個組件使用了什麼,也可以打比較少字~

小結

今天介紹了看起來所向無敵的 memo,但是他還是有弱點的喔!
我怎麼會這樣說呢,明天你就知道了,謝謝大家收看


上一篇
Day 16 useRef 還有什麼作用
下一篇
Day 18 React.memo 聽說你很猛啊,useCallback 表示?
系列文
我與 React 的 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言