iT邦幫忙

2022 iThome 鐵人賽

DAY 14
0
自我挑戰組

我與 React 的 30天系列 第 14

Day 14 props 我不要你了? 讓我們來試試 useContext

  • 分享至 

  • xImage
  •  

一連好幾天都在講 useState 和 useEffect,讓我們來換換口味,講講什麼是 useContext

props 我傳你傳的好累啊

之前我們在用props 傳遞我們要的值時,我們都要一層一層的傳遞 props

也因為每一次都要這樣從父層將傳資料一層一層的傳下來到達我們要的子層,但是我們卻不知道到底哪一層真的使用到了,那我可有其他的方式嗎?那就必須提到我們今天的主題 useContext 了

Context Object

Context Object 是被 createContext() 這個 API 所建立,裡面有兩個子元件

  • Provider: 傳遞 value 這個值
  • Consumer: 接收 value 這個值
import { createContext } from "react";

const TextContext = createContext(context);
const { Provider, Consumer } = TextContext;

那我們要怎麼樣用 Provider, Consumer 傳遞接收我們要的值
首先我做了這個例子

import { createContext } from "react";
import { Parent } from "./Parent";
import "./index.css"

const context = "我是 useContext"

export const TextContext = createContext(context);

function App() {
  return (
    <TextContext.Provider value={context}>
      <div className="border">
        <Parent />
      </div>
    </TextContext.Provider>
  );
}

export default App;

注意!!!!!
Context 目前的值是取決於由上層 component 距離最近的 <MyContext.Provider>value prop。
以我們的例子來說現在的值就是 context = "我是 useContext"

沒錯,在上面也有提到 Provider: 傳遞 value 這個值

那接下來就是我們要如何接球了 那就是用 Consumer: 接收 value 這個值

讓我們看看是怎麼實踐的

// Child.js
import "./index.css"
import { TextContext } from "./App"
import { useContext } from "react";

const Child = () => {

  return (
    <TextContext.Consumer>
      { text => 
        <div className="child" >
          child
          {text}
        </div>
      }
    </TextContext.Consumer>
  )
}

export { Child }

結果會是這樣的,我們可以直接從第一層傳遞給最底下的子層

useContext

這樣寫感覺還是有點小複雜,讓我們換成 useContext 來做吧,我們可以在
TextContext.Consumer 接收 value 的地方換成 useContext

// Child.js
import "./index.css"
import { TextContext } from "./App"
import { useContext } from "react";

const Child = () => {
  const text = useContext(TextContext);

  return (
    <div className="child" >
      child 第三層
      {text}
    </div>
  )
}

export { Child }

不要忘記 useContext 的參數必需為 context object 自己

  • 正確: useContext(MyContext)
  • 錯誤: useContext(MyContext.Consumer)
  • 錯誤: useContext(MyContext.Provider)

所以我們在 App.js,做出了 TextContext 這個 context 物件

const TextContext = createContext(context);

所以我們才會寫出這行

const text = useContext(TextContext);

所以 useContext 能取代 props 嗎?

我認為 useContext 並不能取代原本 props 的方法,因為 context 傳遞的 value 改變時底下所有子元件都會 re-render,
在 React 中我們常常會去改變我們變數的值,像是前幾天介紹的 useState、useEffect,
所以會造成其他沒有沒有用到 useContext 元件的重複渲染

所以還是要依照使用情境的不同去做選擇

小結

今天介紹了 useContext 這個 Hook ,有他的方便之處,也有必須考慮的使用情境,明天將會持續下去,一起繼續探索 React 的世界


上一篇
Day 13用 useEffect 獲取不同的資料(下)
下一篇
Day 15 useRef 就是不讓你 re-render
系列文
我與 React 的 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言