iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
自我挑戰組

我與 React 的 30天系列 第 17 篇

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

  • 分享至 

  • xImage
  •  

我們踏進 React 的世界也將近 20 天了,對於 React 渲染的機制應該也略知一二了...你說你不懂,那就讓我來解釋一下吧,我們一樣做出了 Parent.js 和 Child.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.js 和 Child.js 不需要重新渲染,為什麼?

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

思考之後,我們就可以在我們不需要被渲染的地方加上今天的主角 memo
在 Parent.js 和 Child.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) }}
直播中

尚未有邦友留言

立即登入留言