如何使用 useContext 更改 Context 的值?

IT技术 javascript reactjs react-hooks react-context
2021-04-11 07:57:30

useContextReact 16.8+ 中使用钩子效果很好。您可以创建一个组件、使用钩子并使用上下文值而不会出现任何问题。

我不确定的是如何将更改应用于 Context Provider 值。

1) useContext 钩子严格来说是一种使用上下文值的方法吗?

2) 是否有推荐的方法,使用 React 钩子来更新子组件的值,然后使用useContext此上下文钩子触发任何组件的组件重新渲染

const ThemeContext = React.createContext({
  style: 'light',
  visible: true
});

function Content() {
  const { style, visible } = React.useContext(ThemeContext);

  const handleClick = () => {
    // change the context values to
    // style: 'dark'
    // visible: false
  }

  return (
    <div>
      <p>
        The theme is <em>{style}</em> and state of visibility is 
        <em> {visible.toString()}</em>
      </p>
      <button onClick={handleClick}>Change Theme</button>
    </div>
  )
};

function App() {
  return <Content />
};

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.2/umd/react-dom.production.min.js"></script>

2个回答

如何使用钩子更新上下文在如何避免传递回调?Hooks 常见问题的一部分。

createContext如果使用的组件useContext没有Provider在树上进一步向上,则传递给的参数将仅是默认值您可以改为创建一个Provider提供stylevisibility以及切换它们的功能。

例子

const { createContext, useContext, useState } = React;

const ThemeContext = createContext(null);

function Content() {
  const { style, visible, toggleStyle, toggleVisible } = useContext(
    ThemeContext
  );

  return (
    <div>
      <p>
        The theme is <em>{style}</em> and state of visibility is
        <em> {visible.toString()}</em>
      </p>
      <button onClick={toggleStyle}>Change Theme</button>
      <button onClick={toggleVisible}>Change Visibility</button>
    </div>
  );
}

function App() {
  const [style, setStyle] = useState("light");
  const [visible, setVisible] = useState(true);

  function toggleStyle() {
    setStyle(style => (style === "light" ? "dark" : "light"));
  }
  function toggleVisible() {
    setVisible(visible => !visible);
  }

  return (
    <ThemeContext.Provider
      value={{ style, visible, toggleStyle, toggleVisible }}
    >
      <Content />
    </ThemeContext.Provider>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

你好,所以我们必须将状态函数作为 App.js 中的道具传递给提供者。有没有办法将这些功能放在其他文件(服务或商店)中并导入它?这看起来很复杂,因为 useState 函数和调用它们的函数(例如 toggleVisible)必须在呈现上下文提供程序的组件中。我们不能从其他组件导入它。
2021-05-22 07:57:30
@RandyBurgess 是的,没错。使用钩子创建上下文的工作方式与以前相同,只是您使用useContext钩子而不是Context.Consumer您提到的渲染道具来使用它
2021-05-23 07:57:30
根据上下文文档的警告部分value,每次 Provider 重新渲染时,不会设置这样的对象重新渲染所有消费者吗?
2021-06-04 07:57:30
那么,当使用useState钩子传递给提供者的变量时,如何防止不断重新渲染
2021-06-17 07:57:30
那么说useContexthook的唯一value是它允许您避免使用Context.Consumer组件包装组件并通过函数调用将上下文值传递给呈现的子组件是否正确?
2021-06-19 07:57:30

您可以使用这种方法,无论您有多少嵌套组件,它都可以正常工作。

// Settings Context - src/context/Settings
import React, { useState } from "react";

const SettingsContext = React.createContext();

const defaultSettings = {
  theme: "light",
};

export const SettingsProvider = ({ children, settings }) => {
  const [currentSettings, setCurrentSettings] = useState(
    settings || defaultSettings
  );

  const saveSettings = (values) => {
   setCurrentSettings(values)
  };

  return (
    <SettingsContext.Provider
      value={{ settings: currentSettings, saveSettings }}
    >
      {children}
    </SettingsContext.Provider>
  );
};

export const SettingsConsumer = SettingsContext.Consumer;

export default SettingsContext;
// Settings Hook - src/hooks/useSettings
import { useContext } from "react";
import SettingsContext from "src/context/SettingsContext";

export default () => {
  const context = useContext(SettingsContext);

  return context;
};
// src/index
ReactDOM.render(
  <SettingsProvider settings={settings}>
    <App />
  </SettingsProvider>,
  document.getElementById("root")
);
// Any component do you want to toggle the theme from
// Example: src/components/Navbar
const { settings, saveSettings } = useSettings();

const handleToggleTheme = () => {
  saveSettings({ theme: "light" });
};
Boy FB 知道如何让事情变得复杂,TLDR,请改用 svelte
2021-05-25 07:57:30
@ZiiM 而不是通过编辑这篇文章进行更改....您可以发布更改作为答案...我认为应该保留帖子的原始意图:)
2021-06-08 07:57:30
“无效的钩子调用。钩子只能在函数组件的主体内部调用。”来自钩子
2021-06-13 07:57:30