xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

React useContext Hook All In One

React useContext Hook All In One

React 带有两个内置的 Hooks 来管理本地状态:useState useReducer
如果需要全局状态管理,可以选择加入 React 内置的 useContext Hook 来将 props 从顶层组件传递到底层组件,从而避免 props 多层透传的问题;
这三个 Hooks 足以实现一个强大的状态管理系统

如果过于频繁地使用 React 的 Context 来处理共享/全局状态, Redux 是现在最流行的状态管理库之一;
它允许你管理应用程序的全局状态,任何连接到其全局存储的 React 组件都可以读取和修改这些状态。

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

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  // 如果你在接触 Hook 前已经对 context API 比较熟悉,那应该可以理解
  // useContext(MyContext) 相当于 class 组件中的 static contextType = MyContext 或者 <MyContext.Consumer>。
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

https://reactjs.org/docs/hooks-reference.html#usecontext

https://zh-hans.reactjs.org/docs/hooks-reference.html#usecontext

Context

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。
  // React 会往上找到最近的 theme Provider,然后使用它的值。
  // 在这个例子中,当前的 theme 值为 “dark”。
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

https://zh-hans.reactjs.org/docs/context.html

https://github.com/facebook/react/issues/15156#issuecomment-474590693

React useContext Hook render twice bug ❌

https://codesandbox.io/embed/react-usecontext-hook-render-twice-bug-638z3z?file=/src/Test.jsx:932-970


import React, { useContext, useState, useMemo } from "react";
import "./styles.css";

const themes = {
  light: {
    foreground: "#ffffff",
    background: "#ff00ff"
  },
  dark: {
    foreground: "#000000",
    background: "#00ff00"
  }
};

const ThemeContext = React.createContext(themes.light);

export default function Test() {
  const [theme, setTheme] = useState("light");
  function toggleTheme() {
    if (theme === "light") {
      setTheme("dark");
    } else {
      setTheme("light");
    }
    console.clear();
    // console.log("theme = ", theme);
    const style = `
      background: ${themes[theme].background};
      color: ${themes[theme].foreground};
      font-size: 23px;
    `;
    console.log(`%ctheme = ${theme}`, style);
  }
  return (
    <>
      <button onClick={() => toggleTheme()}>change theme</button>
      <br /> <br />
      <ThemeContext.Provider value={themes[theme]}>
        <Toolbar />
      </ThemeContext.Provider>
    </>
  );
}

function Toolbar() {
  return (
    <div className="App">
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  console.log("❌current theme =", theme);
  return useMemo(() => {
    // The rest of your rendering logic
    // console.log("useMemo ?");
    return (
      <div
        style={{
          background: theme.background,
          color: theme.foreground
        }}
      >
        I am styled by theme context!
      </div>
    );
  }, [theme])
  // return (
  //   <div
  //     style={{
  //       background: theme.background,
  //       color: theme.foreground
  //     }}
  //   >
  //     I am styled by theme context!
  //   </div>
  // );
}


https://github.com/facebook/react/issues/15156

https://stackoverflow.com/questions/63981385/why-does-my-component-render-twice-when-using-reacts-context-api-and-the-useeff

// memo, useMemo

import React, { createContext, useState, useContext, memo, useMemo } from "react";
import ReactDOM from "react-dom";

refs



©xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-05-26 15:56  xgqfrms  阅读(35)  评论(3编辑  收藏  举报