JavaScript >> Javascript 文檔 >  >> React

在 React 中使用 Context API(鉤子和類)

React Context API 是一種本質上創建可以在 React 應用程序中傳遞的全局變量的方法。這是“道具鑽孔”或將道具從祖父母傳給父母傳給孩子的替代方案,依此類推。 Context 通常被吹捧為使用 Redux 進行狀態管理的更簡單、更輕量級的解決方案。我自己還沒有使用過 Redux,但是每次使用 React 的 Context API 時,我都必須查找它,因為它對我來說似乎並不明顯。

我將在這裡留下一些簡短的 Context 入門步驟。

先決條件

  • 如果您還不了解 React 或 React Hooks,請閱讀 React 入門或使用 Hooks 構建 React 應用程序。

創建上下文

想像一下,我有一些信息希望在整個 React 應用程序中隨處可見。可以使用 Context 來實現主題 - 例如,在這個站點上,我有 Context 服務於三個主題:暗模式、亮模式和 MS-DOS 模式(在 404 頁面上)。在這個簡單的示例中,我將使用已登錄的在用戶中。

我將創建上下文,並將其命名為 UserContext .這也會給我 UserContext.ProviderUserContext.Consumer .這兩個組件的作用很簡單:

  • 提供者 - 提供價值的組件
  • 消費者 - 消耗價值的組件

所以我會用 React.createContext() 創建它 在一個名為 UserContext.js 的新文件中 .

src/UserContext.js
import React from 'react'

const UserContext = React.createContext()

export const UserProvider = UserContext.Provider
export const UserConsumer = UserContext.Consumer

export default UserContext

我在這里傳遞了一個空對象值,以表示我稍後可能會通過 API 調用來填充這些數據。你可以用你想要的任何數據預先填充它,以防你不通過 API 檢索數據。

React.createContext(true)

提供上下文

無論您選擇如何使用這些值,提供者始終需要作為父元素的包裝器存在。我將包裝整個 App Provider 中的組件 .我只是在創造一些價值(user ) 並將其作為 Provider 傳遞 價值道具。

src/App.js
import React from 'react'
import HomePage from './HomePage'
import { UserProvider } from './UserContext'

function App() {
  const user = { name: 'Tania', loggedIn: true }

  return (
    <UserProvider value={user}>
      <HomePage />
    </UserProvider>
  )
}

現在任何孩子、孫子、曾孫等都可以訪問 user 作為道具。不幸的是,檢索該值比像使用 this.props 那樣簡單地獲取它稍微複雜一些 或 this.state .

消費上下文

提供 Context 的方式對於類和函數組件是相同的,但兩者的使用方式略有不同。

類組件

從類組件訪問 Context 的最常見方法是通過靜態 contextType .如果您需要 render 之外的 Context 中的值 ,或者在生命週期方法中,你會以這種方式使用它。

src/HomePage.js(類示例)
import React, { Component } from 'react'
import UserContext from './UserContext'

class HomePage extends Component {
  static contextType = UserContext

  componentDidMount() {
    const user = this.context

    console.log(user) // { name: 'Tania', loggedIn: true }
  }

  render() {
    return <div>{user.name}</div>
  }
}

檢索 Context 值的傳統方法是將子組件包裝在 Consumer .從那裡,您將能夠以 props 的形式訪問 value 道具 .您可能仍然會看到這一點,但它更像是一種訪問 Context 的傳統方式。

src/HomePage.js(類示例)
import React, { Component } from 'react'
import { UserConsumer } from './UserContext'

class HomePage extends Component {
  render() {
    return (
      <UserConsumer>
        {(props) => {
          return <div>{props.name}</div>
        }}
      </UserConsumer>
    )
  }
}

函數組件和 Hooks

對於功能組件,您將使用 useContext ,例如在下面的示例中。這相當於 static contextType .

src/HomePage.js
import React, { useContext } from 'react'
import UserContext from './UserContext'

export const HomePage = () => {
  const user = useContext(UserContext)

  return <div>{user.name}</div>
}

更新上下文

更新上下文與更新常規狀態沒有太大區別。我們可以創建一個包裝類,其中包含 Context 的狀態以及更新它的方法。

src/UserContext.js
import React, { Component } from 'react'

const UserContext = React.createContext()

class UserProvider extends Component {
  // Context state
  state = {
    user: {},
  }

  // Method to update state
  setUser = (user) => {
    this.setState((prevState) => ({ user }))
  }

  render() {
    const { children } = this.props
    const { user } = this.state
    const { setUser } = this

    return (
      <UserContext.Provider
        value={{
          user,
          setUser,
        }}
      >
        {children}
      </UserContext.Provider>
    )
  }
}

export default UserContext

export { UserProvider }

現在可以通過 Context 方法更新和查看用戶了。

import React, { Component } from 'react'
import UserContext from './UserContext'

class HomePage extends Component {
  static contextType = UserContext

  render() {
    const { user, setUser } = this.context

    return (
      <div>
        <button
          onClick={() => {
            const newUser = { name: 'Joe', loggedIn: true }

            setUser(newUser)
          }}
        >
          Update User
        </button>
        <p>{`Current User: ${user.name}`}</p>
      </div>
    )
  }
}

在我看來,帶類的 Context API 最大的缺點是你不能使用多個靜態 contextTypes 在一個組件中。這導致需要為應用程序中的所有全局狀態提供一個非常大的上下文,因此對於大型應用程序來說這還不夠。為 Context 創建包裝器的方法也很難測試。

結論

總結一下:

  • 使用 const ___Context = React.createContext() 創建上下文。
  • 拉取___Context.Provider___Context.Consumer 超出 ___Context
  • 包裝 Provider 圍繞你的父組件。
  • 一個類可以使用 static contextType = ___Context
  • 一個功能組件可以使用 const x = useContext(___Context)

希望這會有所幫助!


Tutorial JavaScript 教程
  1. RESTful APIs - Express 簡介

  2. JavaScript 在按鈕單擊時增加計數器編號 |示例代碼

  3. 在 ES6 中解構數組和對象

  4. 我不小心為遊戲玩家建立了一家初創公司😬 |阿祖克

  5. React 中的自定義表單鉤子

  6. NodeJS fs.readFile 的缺點

  7. 作為新手前端開發人員的困惑。

  1. DERN 堆棧,無服務器的 MERN 堆棧的完美替代品

  2. 您的響應式設計是否有效?谷歌分析會告訴你

  3. 正則表達式第 1 部分:簡介

  4. 故事書:以正確的方式進行組件開發

  5. 7 個有用的 JavaScript 技巧和竅門

  6. 在對像數組中,查找屬性與搜索匹配的對象的索引的最快方法

  7. JavaScript 日期比較 |字符串、時間、運算符

  1. 將 Vuex4 與 Vue3 和 Ionic 框架一起使用

  2. 實用 Puppeteer:使用代理瀏覽頁面

  3. 使用 Alpine.js 製作動畫

  4. 如何使用 Socket.IO 並構建您的第一個多人遊戲!