react中context怎么使用

今天小編給大家分享一下react中context怎么使用的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站設(shè)計、成都做網(wǎng)站與策劃設(shè)計,武鄉(xiāng)網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:武鄉(xiāng)等地區(qū)。武鄉(xiāng)做網(wǎng)站價格咨詢:18982081108

在react中,context是一個無需為每層組件手動添加props就能在組件樹之間進行數(shù)據(jù)傳遞的方法;context提供了一種在組件之間共享指定值的方式,而且不必顯式的通過組件樹的逐層傳遞props。

本教程操作環(huán)境:Windows10系統(tǒng)、react17.0.1版、Dell G3電腦。

react中context是什么

Context 提供了一個無需為每層組件手動添加 props,就能在組件樹間進行數(shù)據(jù)傳遞的方法。在一個典型的 React 應(yīng)用中,數(shù)據(jù)是通過 props 屬性自上而下(由父及子)進行傳遞的,但這種做法對于某些類型的屬性而言是極其繁瑣的(例如:地區(qū)偏好,UI 主題),這些屬性是應(yīng)用程序中許多組件都需要的。Context 提供了一種在組件之間共享此類值的方式,而不必顯式地通過組件樹的逐層傳遞 props。

Context 什么時候用?

Context 設(shè)計目的是為了共享那些對于一個組件樹而言是“全局”的數(shù)據(jù),例如當(dāng)前認證的用戶、主題或首選語言。舉個例子,在下面的代碼中,我們通過一個 “theme” 屬性手動調(diào)整一個按鈕組件的樣式

class App extends React.Component {
  render() {
    return <Toolbar theme="dark" />;
  }
}

function Toolbar(props) {
  // Toolbar 組件接受一個額外的“theme”屬性,然后傳遞給 ThemedButton 組件。
  // 如果應(yīng)用中每一個單獨的按鈕都需要知道 theme 的值,這會是件很麻煩的事,
  // 因為必須將這個值層層傳遞所有組件。
  return (
    <p>
      <ThemedButton theme={props.theme} />
    </p>
  );
}

class ThemedButton extends React.Component {
  render() {
    return <Button theme={this.props.theme} />;
  }
}

// 通過props傳遞:App -> Toolbar -> ThemedButton
// 如果嵌套很深,那么需要逐層傳遞props,即使中間不需要該props,顯得很繁瑣

使用 context, 我們可以避免通過中間元素傳遞 props

// Context 可以讓我們無須明確地傳遍每一個組件,就能將值深入傳遞進組件樹。
// 為當(dāng)前的 theme 創(chuàng)建一個 context("light"為默認值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
    // 使用一個 Provider 來將當(dāng)前的 theme 傳遞給以下的組件樹。
    // 無論多深,任何組件都能讀取這個值。
    // 在這個例子中,我們將 “dark” 作為當(dāng)前的值傳遞下去。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中間的組件再也不必指明往下傳遞 theme 了。
function Toolbar() {
  return (
    <p>
      <ThemedButton />
    </p>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 讀取當(dāng)前的 theme context。
  // React 會往上找到最近的 theme Provider,然后使用它的值。
  // 在這個例子中,當(dāng)前的 theme 值為 “dark”。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}
// 也可以使用 ThemedButto.contextType = ThemeContext;

API介紹

React.createContext

const MyContext = React.createContext(defaultValue);

創(chuàng)建一個 Context 對象。當(dāng) React 渲染一個訂閱了這個 Context 對象的組件,這個組件會從組件樹中離自身最近的那個匹配的 Provider 中讀取到當(dāng)前的 context 值。

只有當(dāng)組件所處的樹中沒有匹配到 Provider 時,其 defaultValue 參數(shù)才會生效。這有助于在不使用 Provider 包裝組件的情況下對組件進行測試。注意:將 undefined 傳遞給 Provider 的 value 時,消費組件的 defaultValue 不會生效。

Context.Provider

<MyContext.Provider value={/* 某個值 */}>

每個 Context 對象都會返回一個 Provider React 組件,它允許消費組件訂閱 context 的變化。

Provider 接收一個 value 屬性,傳遞給消費組件。一個 Provider 可以和多個消費組件有對應(yīng)關(guān)系。多個 Provider 也可以嵌套使用,里層的會覆蓋外層的數(shù)據(jù)。

當(dāng) Provider 的 value 值發(fā)生變化時,它內(nèi)部的所有消費組件都會重新渲染。Provider 及其內(nèi)部 consumer 組件都不受制于 shouldComponentUpdate 函數(shù),因此當(dāng) consumer 組件在其祖先組件退出更新的情況下也能更新。

Class.contextType

掛載在 class 上的 contextType 屬性會被重賦值為一個由 React.createContext() 創(chuàng)建的 Context 對象。這能讓你使用 this.context 來消費最近 Context 上的那個值。你可以在任何生命周期中訪問到它,包括 render 函數(shù)中

import MyContext from './MyContext';

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在組件掛載完成后,使用 MyContext 組件的值來執(zhí)行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 組件的值進行渲染 */
  }
  // 或者如上邊例子一樣使用 static contextType = MyContext;
}
MyClass.contextType = MyContext;

Context.Consumer

import MyContext from './MyContext';

function ToolList() {
  return (
    <MyContext.Consumer
      {value => /* 基于 context 值進行渲染*/}
    </MyContext.Consumer>
  )
}

這里,React 組件也可以訂閱到 context 變更。這能讓你在函數(shù)式組件中完成訂閱 context。

這需要函數(shù)作為子元素(function as a child)這種做法。這個函數(shù)接收當(dāng)前的 context 值,返回一個 React 節(jié)點。傳遞給函數(shù)的 value 值等同于往上組件樹離這個 context 最近的 Provider 提供的 value 值。如果沒有對應(yīng)的 Provider,value 參數(shù)等同于傳遞給 createContext()defaultValue。

Context.displayName

context 對象接受一個名為 displayName 的 property,類型為字符串。React DevTools 使用該字符串來確定 context 要顯示的內(nèi)容。

如下述組件在 DevTools 中將顯示為 MyDisplayName

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';

<MyContext.Provider>   // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer>   // "MyDisplayName.Consumer" 在 DevTools 中

示例

動態(tài) Context

對于上面的 theme 例子,使用動態(tài)值(dynamic values)后更復(fù)雜的用法

theme-context.js

export const themes = {
  light: {
    foreground: '#000000',
    background: '#eeeeee',
  },
  dark: {
    foreground: '#ffffff',
    background: '#222222',
  },
};

export const ThemeContext = React.createContext(themes.dark);   // 該處為默認值

themed-button.js

import { ThemeContext } from './theme-context';

class ThemedButton extends React.Component {
  render() {
    let props = this.props;
    // 獲取到ThemeContext中的默認值
    let theme = this.context;
    return (
      <button
        {...props}
        style={{backgroundColor: theme.background}}
      />
    );
  }
  // static contextType = ThemeContext;
}
ThemedButton.contextType = ThemeContext;

export default ThemedButton;

app.js

import { ThemeContext, themes } from './theme-context';
import ThemedButton from './themed-button';

// 一個使用 ThemedButton 的中間組件
function Toolbar(props) {
  return (
    <ThemedButton onClick={props.changeTheme}>
      Change Theme
    </ThemedButton>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      theme: themes.light,
    };

    this.toggleTheme = () => {
      this.setState(state => ({
        theme: state.theme === themes.dark ? themes.light : themes.dark,
      }));
    };
  }

  render() {
    // 在 ThemeProvider 內(nèi)部的 ThemedButton 按鈕組件使用 state 中的 theme 值,
    // 而外部的組件使用默認的 theme 值
    return (
      <Page>
        <ThemeContext.Provider value={this.state.theme}>
          <Toolbar changeTheme={this.toggleTheme} />
        </ThemeContext.Provider>
        <Section>
          <ThemedButton />
        </Section>
      </Page>
    );
  }
}

ReactDOM.render(<App />, document.root);

// 使用ThemeContext.Provider包裹的組件,可以消費到ThemeContext中的value
// 即Toolbar、ThemedButton中都可以使用this.context來獲取到value
// 注意觀察,更新state的方法是通過props向下傳遞,由子孫組件觸發(fā)更新,下面會講到通過context的方式傳遞更新函數(shù)

在嵌套組件中更新 Context

在上面的例子中,我們通過 props 的方式向下傳遞一個更新函數(shù),從而改變 App 中 themes 的值。我們知道,從一個在組件樹中嵌套很深的組件中更新 context 是很有必要的。在這種場景下,你可以通過 context 傳遞一個函數(shù),使得 consumers 組件更新 context

theme-context.js

// 確保傳遞給 createContext 的默認值數(shù)據(jù)結(jié)構(gòu)是調(diào)用的組件(consumers)所能匹配的!
export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},   // 定義更新主題的方法,向下傳遞
});

theme-toggler-button.js

import { ThemeContext } from './theme-context';

function ThemeTogglerButton() {
  // Theme Toggler 按鈕不僅僅只獲取 theme 值,它也從 context 中獲取到一個 toggleTheme 函數(shù)(下面app.js部分)
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button onClick={toggleTheme} style={{backgroundColor: theme.background}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

export default ThemeTogglerButton;

app.js

import { ThemeContext, themes } from './theme-context';
import ThemeTogglerButton from './theme-toggler-button';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggleTheme = () => {
      this.setState(state => ({
        theme: state.theme === themes.dark ? themes.light : themes.dark,
      }));
    };

    // State 也包含了更新函數(shù),因此它會被傳遞進 context provider。
    this.state = {
      theme: themes.light,
      toggleTheme: this.toggleTheme,   // 定義更新函數(shù),通過context方式向下傳遞
    };
  }

  render() {
    // 整個 state 都被傳遞進 provider
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}

function Content() {
  return (
    <p>
      <ThemeTogglerButton />
    </p>
  );
}

ReactDOM.render(<App />, document.root);

消費多個 Context

為了確保 context 快速進行重渲染,React 需要使每一個 consumers 組件的 context 在組件樹中成為一個單獨的節(jié)點

// Theme context,默認的 theme 是 "light" 值
const ThemeContext = React.createContext('light');

// 用戶登錄 context
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
  render() {
    const { signedInUser, theme } = this.props;

    // 提供初始 context 值的 App 組件
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

function Layout() {
  return (
    <p>
      <Sidebar />
      <Content />
    </p>
  );
}

// 一個組件可能會消費多個 context
function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  );
}

如果兩個或者更多的 context 值經(jīng)常被一起使用,那你可能要考慮一下另外創(chuàng)建你自己的渲染組件,以提供這些值。

注意事項

因為 context 會使用參考標(biāo)識(reference identity)來決定何時進行渲染,這里可能會有一些陷阱,當(dāng) provider 的父組件進行重渲染時,可能會在 consumers 組件中觸發(fā)意外的渲染。舉個例子,當(dāng)每一次 Provider 重渲染時,以下的代碼會重渲染所有下面的 consumers 組件,因為 value 屬性總是被賦值為新的對象

class App extends React.Component {
  render() {
    return (
      <MyContext.Provider value={{something: 'something'}}>
        <Toolbar />
      </MyContext.Provider>
    );
  }
}

為了防止這種情況,將 value 狀態(tài)提升到父節(jié)點的 state 里

class App extends React.Component {
  constructor(props) {
    super(props);
    // 多次渲染,state 會被保留,當(dāng)value不變時,下面的 consumers 組件不會重新渲染 
    this.state = {
      value: {something: 'something'},
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

以上就是“react中context怎么使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享題目:react中context怎么使用
標(biāo)題網(wǎng)址:http://muchs.cn/article26/gheicg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣營銷型網(wǎng)站建設(shè)網(wǎng)站設(shè)計、軟件開發(fā)、定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管