У меня есть языковые настройки в контексте, как показано ниже
class LanguageProvider extends Component {
static childContextTypes = {
langConfig: PropTypes.object,
};
getChildContext() {
return { langConfig: 'en' };
}
render() {
return this.props.children;
}
}
export default LanguageProvider;
Код моего приложения будет примерно таким, как показано ниже
<LanguageProvider>
<App>
<MyPage />
</App>
</LanguageProvider>
На моей странице есть компонент для переключения языка
<MyPage>
<LanguageSwitcher/>
</MyPage>
LanguageSwitcher
в этом случае MyPage
необходимо обновить контекст, чтобы изменить язык на 'jp', как показано ниже
class LanguageSwitcher extends Component {
static contextTypes = {
langConfig: PropTypes.object,
};
updateLanguage() {
//Here I need to update the langConfig to 'jp'
}
render() {
return <button onClick={this.updateLanguage}>Change Language</button>;
}
}
export default LanguageSwitcher;
Как я могу обновить контекст внутри компонента LanguageSwitcher?
javascript
reactjs
react-context
Mshameer
источник
источник
Ответы:
Использование крючков
Хуки были введены в 16.8.0, поэтому для следующего кода требуется минимальная версия 16.8.0 (прокрутите вниз, чтобы увидеть пример компонентов класса). Демонстрация CodeSandbox
1. Установка родительского состояния для динамического контекста
Во-первых, чтобы иметь динамический контекст, который можно передавать потребителям, я буду использовать родительское состояние. Это гарантирует, что у меня будет единый источник истины. Например, мое родительское приложение будет выглядеть так:
const App = () => { const [language, setLanguage] = useState("en"); const value = { language, setLanguage }; return ( ... ); };
language
Хранится в состоянии. Позже мы передадим обе функцииlanguage
и функцию установкиsetLanguage
через контекст.2. Создание контекста
Затем я создал такой языковой контекст:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Здесь я устанавливаю значения по умолчанию для
language
('en') иsetLanguage
функцию, которая будет отправлена поставщиком контекста потребителю (ям). Это только значения по умолчанию, и я предоставлю их значения при использовании компонента поставщика в родительском элементеApp
.Примечание:
LanguageContext
остается то же самое, если вы3. Создание потребителя контекста
Чтобы переключатель языка устанавливал язык, он должен иметь доступ к функции настройки языка через контекст. Это может выглядеть примерно так:
const LanguageSwitcher = () => { const { language, setLanguage } = useContext(LanguageContext); return ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> ); };
Здесь я просто устанавливаю язык на «jp», но у вас может быть собственная логика для установки языков для этого.
4. Заключение потребителя в провайдера.
Теперь я визуализирую свой компонент переключателя языка в a
LanguageContext.Provider
и передаю значения, которые должны быть отправлены через контекст на любой более глубокий уровень. Вот какApp
выглядят мои родители :const App = () => { const [language, setLanguage] = useState("en"); const value = { language, setLanguage }; return ( <LanguageContext.Provider value={value}> <h2>Current Language: {language}</h2> <p>Click button to change to jp</p> <div> {/* Can be nested */} <LanguageSwitcher /> </div> </LanguageContext.Provider> ); };
Теперь при каждом нажатии переключателя языка контекст обновляется динамически.
Демонстрация CodeSandbox
Использование компонентов класса
Последний контекстный API был представлен в React 16.3, который обеспечивает отличный способ создания динамического контекста. Для следующего кода требуется минимальная версия 16.3.0. Демонстрация CodeSandbox
1. Установка родительского состояния для динамического контекста
Во-первых, чтобы иметь динамический контекст, который можно передавать потребителям, я буду использовать родительское состояние. Это гарантирует, что у меня будет единый источник истины. Например, мое родительское приложение будет выглядеть так:
class App extends Component { setLanguage = language => { this.setState({ language }); }; state = { language: "en", setLanguage: this.setLanguage }; ... }
language
Хранится в состоянии наряду с методом языка сеттер, который вы можете держать вне государственного дерева.2. Создание контекста
Затем я создал такой языковой контекст:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Здесь я устанавливаю значения по умолчанию для
language
('en') иsetLanguage
функцию, которая будет отправлена поставщиком контекста потребителю (ям). Это только значения по умолчанию, и я предоставлю их значения при использовании компонента поставщика в родительском элементеApp
.3. Создание потребителя контекста
Чтобы переключатель языка устанавливал язык, он должен иметь доступ к функции настройки языка через контекст. Это может выглядеть примерно так:
class LanguageSwitcher extends Component { render() { return ( <LanguageContext.Consumer> {({ language, setLanguage }) => ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> )} </LanguageContext.Consumer> ); } }
Здесь я просто устанавливаю язык на «jp», но у вас может быть собственная логика для установки языков для этого.
4. Заключение потребителя в провайдера.
Теперь я визуализирую свой компонент переключателя языка в a
LanguageContext.Provider
и передаю значения, которые должны быть отправлены через контекст на любой более глубокий уровень. Вот какApp
выглядят мои родители :class App extends Component { setLanguage = language => { this.setState({ language }); }; state = { language: "en", setLanguage: this.setLanguage }; render() { return ( <LanguageContext.Provider value={this.state}> <h2>Current Language: {this.state.language}</h2> <p>Click button to change to jp</p> <div> {/* Can be nested */} <LanguageSwitcher /> </div> </LanguageContext.Provider> ); } }
Теперь при каждом нажатии переключателя языка контекст обновляется динамически.
Демонстрация CodeSandbox
источник
Provider
?value
откажется, потребитель будет использовать значения по умолчанию.setLanguage: (language: string) => {}
работает для меня.Приведенный выше ответ Maithani - отличное решение, но это компонент класса без использования крючков. Поскольку React рекомендует использовать функциональные компоненты и хуки, я буду реализовывать это с хуками useContext и useState. Вот как вы можете обновить контекст из дочернего компонента.
LanguageContextMangement.js
import React, { useState } from 'react' export const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} }) export const LanguageContextProvider = (props) => { const setLanguage = (language) => { setState({...state, language: language}) } const initState = { language: "en", setLanguage: setLanguage } const [state, setState] = useState(initState) return ( <LanguageContext.Provider value={state}> {props.children} </LanguageContext.Provider> ) }
App.js
import React, { useContext } from 'react' import { LanguageContextProvider, LanguageContext } from './LanguageContextManagement' function App() { const state = useContext(LanguageContext) return ( <LanguageContextProvider> <button onClick={() => state.setLanguage('pk')}> Current Language is: {state.language} </button> </LanguageContextProvider> ) } export default App
источник
() => {}
state.setLanguage('pk')
ничего не будет, так как онconst state = useContext(LanguageContext)
находится за пределамиLanguageContextProvider
. Я решил свою проблему, переместив провайдера на один уровень вверх, а затем используяuseContext
для ребенка уровень ниже.<LanguageContext.Consumer> {value => /* access your value here */} </LanguageContext.Consumer>
.Одно довольно простое решение - установить состояние в вашем контексте, включив метод setState в ваш провайдер следующим образом:
return ( <Context.Provider value={{ state: this.state, updateLanguage: (returnVal) => { this.setState({ language: returnVal }) } }}> {this.props.children} </Context.Provider> )
И в своем потребителе вызовите updateLanguage следующим образом:
// button that sets language config <Context.Consumer> {(context) => <button onClick={context.updateLanguage({language})}> Set to {language} // if you have a dynamic val for language </button> <Context.Consumer>
источник