91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

react?context優化的方法有哪些

發布時間:2022-12-14 17:58:15 來源:億速云 閱讀:122 作者:iii 欄目:開發技術

本篇內容介紹了“react context優化的方法有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    一、前言

    我們在使用react的過程中,經常會遇到需要跨層級傳遞數據的情況。props傳遞數據應用在這種場景下會極度繁瑣,且不利于維護,于是context應運而生

    官方解釋: Context 提供了一種在組件之間共享此類值的方式,而不必顯式地通過組件樹的逐層傳遞 props

    二、用法

    在正文之前,先簡單介紹一下context的三種消費方法:

    • 1.通過Consumer來消費上下文

    const globalContext = React.createContext();
    class TestUseContextSon1 extends React.Component {
      render() {
        return (
          <globalContext.Consumer>
            {(value) => {
              return <div>{value.num}</div>;
            }}
          </globalContext.Consumer>
        );
      }
    }
    export default class TestUseContext extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          num: 2,
        };
      }
      render() {
        return (
          <globalContext.Provider value={{ num: this.state.num }}>
            <TestUseContextSon1 />
          </globalContext.Provider>
        );
      }
    }
    • 2.通過靜態變量contextType來消費上下文

    const globalContext = React.createContext();
    class TestUseContextSon2 extends React.Component {
      static contextType = globalContext;
      render() {
        return <div>{this.context.num}</div>;
      }
    }
    export default class TestUseContext extends React.Component {
      ...省略...
      render() {
        return (
          <globalContext.Provider value={{ num: this.state.num }}>
            <TestUseContextSon2 />
          </globalContext.Provider>
        );
      }
    }
    • 3.通過hooks useContext來消費上下文

    const globalContext = React.createContext();
    const TestUseContextSon3 = (props) => {
      const con = useContext(globalContext);
      return <div>{con.num}</div>;
    };
    export default class TestUseContext extends React.Component {
      ...省略...
      render() {
        return (
          <globalContext.Provider value={{ num: this.state.num }}>
            <TestUseContextSon3 />
          </globalContext.Provider>
        );
      }
    }

    比較:

    • Consumer既可以在類組件中使用,也可以在函數組件中使用

    • contextType只能在類組件中使用

    • useContext只能在函數組件中使用

    三、缺點

    這里有一個例子:

    import React, { useState } from "react";
    const globalContext = React.createContext();
    const Son1 = () => {
      return <div>Son1</div>;
    };
    const Son2 = () => {
      const value = useContext(globalContext);
      return <div>Son2---{value.num}</div>;
    };
    export const Demo = () => {
      const [value, setValue] = useState({ num: 1 });
      return (
        <globalContext.Provider value={value}>
          <Son1 />
          <Son2 />
        </globalContext.Provider>
      );
    };

    當我們改變value值時,會導致Son1Son2都發生重渲染,但這與我們的初衷相悖,造成了額外的開銷,我們期望做到的是Son1不執行,Son2重新渲染。在較長的一段時間內,我都認為是使用了context導致Provider下面的子組件發生了重渲染。網上也有很多解釋沒有說清楚,容易誤導人。

    實際情況是value的變化導致了Son1Son2發生重渲染。如下示例: 即使我們不使用&middot;context,當value發生變化時,Son1Son2也會重渲染。

    const Son1 = () => {
      return <div>Son1</div>;
    };
    const Son2 = () => {
      return <div>Son2</div>;
    };
    export const Demo = () => {
      const [value, setValue] = useState({ num: 1 });
      return (
        <Son1 />
        <Son2 />
      );
    };

    那么問題來了,我們使用context的時候,必然要向<globalContext.Provider value={value}>Provider的value中傳入一個狀態,但是當狀態改變時又不可避免的造成Provider下的所有子組件重新渲染,我們期望只有消費了上下文的子組件重新渲染,那么有什么方法能夠避免這種額外的開銷嗎?

    四、context優化

    我們知道,所有消費了context的地方,只要Providervalue值發生變化,都會發生重渲染.只要我們有什么辦法能夠避開父組件狀態發生變化,引起的子組件狀態發生變化,那就可以減少很多不必要的開銷。

    一重奏--使用PureComponent

    const globalContext = React.createContext();
    class TestUseContextSon2 extends React.PureComponent {
      constructor(props) {
        super(props);
        this.state = {};
      }
      render() {
        console.log("TestUseContextSon2----render");
        return (
          <globalContext.Consumer>
            {(value) => {
              console.log("Consumer----handle");
              return <div>{value.num}</div>;
            }}
          </globalContext.Consumer>
        );
      }
    }
    const TestUseContext = () => {
      const [value, setValue] = useState({ num: 1 });
      return (
          <globalContext.Provider value={value}>
            <button onClick={() => setValue({ num: value.num + 1 })}>
              點擊
            </button>
            <TestUseContextSon2 />
          </globalContext.Provider>
      );
    }

    react?context優化的方法有哪些

    初始化的時候,兩個console各執行一遍

    react?context優化的方法有哪些

    點擊按鈕之后,TestUseContextSon2----render沒有打印,Consumer----handle打印,達到預期結果。

    二重奏--使用shouldComponentUpdate

    此處由于作者比較任性,省略100字,基本效果其實和PureComponent一致,不做過多描述。

    三重奏--使用React.memo

    React.memo既可以用于函數組件,也可以用于類組件

    const globalContext = React.createContext();
    const TestUseContextSon3 = React.memo(function (props) {
      console.log("TestUseContextSon3----render");
      return (
          <globalContext.Consumer>
            {(value) => {
              console.log("Consumer----handle");
              return <div>{value.num}</div>;
            }}
          </globalContext.Consumer>
        );
    });
    const TestUseContext = () => {
      const [value, setValue] = useState({ num: 1 });
      return (
          <globalContext.Provider value={value}>
            <button onClick={() => setValue({ num: value.num + 1 })}>
              點擊
            </button>
            <TestUseContextSon3 />
          </globalContext.Provider>
      );
    }

    react?context優化的方法有哪些

    點擊按鈕之后,TestUseContextSon2----render沒有打印,Consumer----handle打印,達到預期結果。 那如果我們使用useContext來消費上下文呢?

    const TestUseContextSon4 = React.memo(function (props) {
      const con = useContext(globalContext);
      console.log("TestUseContextSon4----render");
      return &lt;div&gt;{con.num}&lt;/div&gt;;
    });

    react?context優化的方法有哪些

    點擊按鈕之后,TestUseContextSon4----render打印,也就是說當我們使用useContext來消費上下文的時候,整個函數組件會重新執行。而Consumer僅僅只是局部執行,這意味更少的性能消耗。

    四重奏--Provider再封裝+props.children

    上面所述的三種方法都存在一個弊端,Provider的直接下級組件都需要用memoPureComponentshouldComponentUpdate處理,才能屏蔽掉父級狀態變化帶來的影響,那么有沒有一種更方便的方式呢?

    代碼如下:

    /** 主題 */
    const ThemeContext = React.createContext({ theme: "red" });
    const ThemeProvider = (props) => {
      const [theme, setTheme] = useState({ theme: "red" });
      console.log("ThemeProvider-----", theme.theme);
      return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
          {props.children}
        </ThemeContext.Provider>
      );
    };
    const Son1 = function (props) {
      const { setTheme } = useContext(ThemeContext);
      return <button onClick={() => setTheme({ theme: "blue" })}>改變主題</button>;
    };
    const Son2 = function (props) {
      const { theme } = useContext(ThemeContext);
      console.log("Son2----", theme.theme);
      return <div>主題----{theme.theme}</div>;
    };
    const Son4 = function (props) {
      console.log("Son4---沒有使用上下文");
      return <div>沒有使用上下文</div>;
    };
    export default class ContextChildren extends React.Component {
      render() {
        return (
          <ThemeProvider>
            <Son1 />
            <Son2 />
            <Son4 />
          </ThemeProvider>
        );
      }
    }

    在上面這段代碼中,<Son1 /><Son2 /><Son3 />并沒有直接放到ThemeContext.Provider組件下面,而是將該組件再次封裝成ThemeProvider組件,并將狀態管理也放在ThemeProvider組件中,然后通過props.children來引入組件子節點。

    效果如下:

    react?context優化的方法有哪些

    當我們點擊按鈕時,打印如下:

    react?context優化的方法有哪些

    點擊按鈕,setTheme執行,狀態由{ theme: "red" }變為{ theme: "blue" },引起ThemeProvider組件重新執行,打印ThemeProvider----- blue,組件Son2由于消費了上下文,重新執行,打印Son2---- blue

    那么問題來了,為什么沒有打印Son4呢?我們沒有使用memo、PureComponent等處理Son4組件,但是它確實不會重新執行。

    出現這種現象,其實是props.children引起的,props.children指向一個對象,這個對象中存放著<Son1 /><Son2 /><Son3 />執行的結果,ThemeProvider執行的時候,props.children指向的對象沒有發生變化,只有當ContextChildren組件重新渲染的時候,<Son1 /><Son2 /><Son3 />才會重新執行,由于我們將狀態放置于ThemeProvider組件中,所以ContextChildren組件不會重新渲染,<Son1 /><Son2 /><Son3 />也就不會重新執行,所以Son4---沒有使用上下文沒有打印。

    那如果將ThemeProvider組件改成這樣呢?

    const ThemeProvider = (props) => {
      const [theme, setTheme] = useState({ theme: "red" });
      console.log("ThemeProvider-----", theme.theme);
      const content = React.Children.map(props.children, (child) => {
        return child;
      });
      return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
          {content}
        </ThemeContext.Provider>
      );
    };

    Son4依然沒有執行

    react?context優化的方法有哪些

    再改一下:

    const ThemeProvider = (props) => {
      const [theme, setTheme] = useState({ theme: "red" });
      console.log("ThemeProvider-----", theme.theme);
      const content = React.Children.map(props.children, (child) => {
        return React.cloneElement(child);
      });
      return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
          {content}
        </ThemeContext.Provider>
      );
    };

    我們使用React.cloneElementapi克隆一下child

    react?context優化的方法有哪些

    Son4執行了,我想這是因為克隆之后指向發生變化,導致組件重新執行

    “react context優化的方法有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    正蓝旗| 涞源县| 武宣县| 柳河县| 五大连池市| 通州区| 清新县| 浦县| 永川市| 上杭县| 盘山县| 桂阳县| 宜兰市| 留坝县| 白玉县| 宾川县| 偏关县| 四会市| 眉山市| 文山县| 嵊泗县| 扬中市| 宁安市| 油尖旺区| 苗栗县| 桓仁| 德格县| 长葛市| 阿城市| 穆棱市| 庆城县| 孙吴县| 喀喇| 德兴市| 西安市| 平顶山市| 龙江县| 从江县| 泗洪县| 伊川县| 清新县|