useContext Hook 是如何工做的

想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!html


阿里雲最近在作活動,低至2折,有興趣能夠看看promotion.aliyun.com/ntms/yunpar…前端


爲了保證的可讀性,本文采用意譯而非直譯。react

全部這些新的React Hook之間都有一個宗旨:就是爲了使函數組件像類組件同樣強大。git

useContext hook 與其它幾個有點不同,但它在特定場景下仍是頗有用的。github

React 的 Context API 是一種在應用程序中深刻傳遞數據的方法,而無需手動一個一個在多個父子孫之間傳遞 prop。當我們須要的只是傳遞數據時,它能夠做爲像Redux這樣的工具的一個很好的替代。數組

使用 Context ,首先頂層先聲明 Provier 組件,並聲明 value 屬性,接着在後代組件中聲明 Consumer 組件,這個 Consumer 子組件,只能是惟一的一個函數,函數參數便是 Context 的負載。若是有多個 Context ,ProviderConsumer 任意的順序嵌套便可。dom

此外咱們還能夠針對任意一個 Context 使用 contextType 來簡化對這個 Context 負載的獲取。但在一個組件中,即便消費多個 Context,contextType 也只能指向其中一個。ide

Hooks 環境中,依舊可使用 Consumer,可是 ContextType 做爲類靜態成員確定是用不了。Hooks 提供了 useContext,不但解決了 Consumer 難用的問題同時也解決了 contextType 只能使用一個 context 的問題。函數

標準方式

使用 API的典型方法以下所示:工具

import React from "react";
import ReactDOM from "react-dom";

// 建立 Context
const NumberContext = React.createContext();
// 它返回一個具備兩個值的對象
// { Provider, Consumer }

function App() {
  // 使用 Provider 爲全部子孫代提供 value 值 
  return (
    <NumberContext.Provider value={42}>
      <div>
        <Display />
      </div>
    </NumberContext.Provider>
  );
}

function Display() {
  // 使用 Consumer 從上下文中獲取 value
  return (
    <NumberContext.Consumer>
      {value => <div>The answer is {value}.</div>}
    </NumberContext.Consumer>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));
複製代碼

能夠 CodeSandbox上看看運行效果。

使用 useContext 方式

使用 useContext hook 來重寫上面的示例

import React, { useContext } from 'react';

// ...

function Display() {
  const value = useContext(NumberContext);
  return <div>The answer is {value}.</div>;
}
複製代碼

調用useContext,傳入從React.createContext獲取的上下文對象。

惟一須要注意的是你必須將整個上下文對象傳遞給useContext - 而不只僅是Consumer, 固然若是忘記了,React會給出警告。

嵌套的 Consumers

你可能遇到這樣的狀況,我們的組件須要從多個父上下文中接收數據,從而致使這樣的代碼

function HeaderBar() {
  return (
    <CurrentUser.Consumer>
      {user =>
        <Notifications.Consumer>
          {notifications =>
            <header>
              Welcome back, {user.name}!
              You have {notifications.length} notifications.
            </header>
          }
      }
    </CurrentUser.Consumer>
  );
}
複製代碼

這種大量嵌套只是爲了接收兩個值。下面是使用useContext時的效果:

function HeaderBar() {
  const user = useContext(CurrentUser);
  const notifications = useContext(Notifications);

  return (
    <header>
      Welcome back, {user.name}!
      You have {notifications.length} notifications.
    </header>
  );
}
複製代碼

總結

useContext 接收一個 context 對象(React.createContext 的返回值)並返回該 context 的當前值。當前的 context 值由上層組件中距離當前組件最近的 <CountContext.Provider>value prop 決定。

當組件上層最近的 <CountContext.Provider> 更新時,該 Hook 會觸發重渲染,並使用最新傳遞給 CountContext provider 的 context value 值。

別忘記 useContext 的參數必須是 context 對象自己:

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

調用了 useContext 的組件總會在 context 值變化時從新渲染。若是重渲染組件的開銷較大,你能夠 經過使用 memoization 來優化。

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

參考:

daveceddia.com/usecontext-…

交流(歡迎加入羣,羣工做日都會發紅包,互動討論技術)

阿里雲最近在作活動,低至2折,有興趣能夠看看:promotion.aliyun.com/ntms/yunpar…

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

github.com/qq449245884…

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索