Использование хука useContext с React 16.8+ работает хорошо. Вы можете создать компонент, использовать хук и значения контекста без каких-либо проблем.
В чем я не уверен, так это в том, как применить изменения к значениям поставщика контекста.
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>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Как обновить контекст с помощью хуков, обсуждается в части Как избежать передачи обратных вызовов вниз? FAQ по хукам.
Аргумент, переданный createContext, будет значением по умолчанию, только если компонент, который использует useContext, не имеет Provider над ним выше по дереву. Вместо этого вы можете создать Provider, который предоставляет 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"));<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>@RandyBurgess Да, верно. Создание контекста с помощью хуков работает так же, как и раньше, просто вы используете его с помощью хука useContext, а не Context.Consumer с помощью рендеринга, о котором вы упомянули.
Не приведет ли установка value к объекту, подобному этому, к повторному рендерингу всех потребителей каждый раз, когда провайдер повторно рендерит, на раздел оговорок контекстной документации?
Так как же предотвратить постоянный повторный рендеринг при использовании хука useState для переменной, которая передается провайдеру?
Здравствуйте, поэтому мы должны передать функции состояний провайдеру в качестве реквизита в App.js. Есть ли способ поместить эти функции в другой файл (сервис или магазин) и импортировать его? Это кажется сложным, потому что функции useState и функции, которые их вызывают (например, toggleVisible), должны быть в компоненте, который отображает поставщика контекста. Мы не можем импортировать его из другого компонента.
Ожидаемый тип исходит из свойства «значение», которое объявлено здесь для типа «IntrinsicAttributes & ProviderProps <null>» — поскольку мы установили createContext с нулевым значением, я не могу передать данные в реквизиты значения.
Вы можете использовать этот подход, независимо от того, сколько у вас вложенных компонентов, он будет работать нормально.
// 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" });
};
«Неверный вызов ловушки. Хуки можно вызывать только внутри тела функционального компонента».
@ZiiM Вместо того, чтобы вносить изменения, редактируя этот пост .... вы можете опубликовать эти изменения в качестве ответа ... Я думаю, что первоначальный замысел сообщения должен быть сохранен :)
Boy FB знает, как все усложнять, TLDR, вместо этого используйте svelte
Так правильно ли говорить, что единственное значение хука
useContextзаключается в том, что он позволяет вам избежать обертывания компонента родителемContext.Consumerи передачи значения контекста через вызов функции визуализируемому дочернему элементу?