如何在使用useContext的React Hook时更改Context值

时间:2019-02-17 23:31:22

标签: javascript reactjs react-hooks react-context

在React 16.8+中使用useContext钩子效果很好。您可以创建一个组件,使用该钩子,并充分利用上下文值。

我不确定如何将更改应用于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 个答案:

答案 0 :(得分:11)

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

// 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"});
};

答案 1 :(得分:9)

Hooks常见问题解答的How to avoid passing callbacks down?部分讨论了如何使用钩子更新上下文。

仅当使用https://github.com/organizations/<YOUR_ORGANIZATION_NAME>/settings/oauth_application_policy的组件在树的上方没有createContext时,传递给useContext的参数才是默认值。相反,您可以创建提供ProviderProvider以及切换它们的功能的style

示例

visibility
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"));