Eu tenho as configurações de idioma no contexto como abaixo
class LanguageProvider extends Component {
static childContextTypes = {
langConfig: PropTypes.object,
};
getChildContext() {
return { langConfig: 'en' };
}
render() {
return this.props.children;
}
}
export default LanguageProvider;
Meu código de aplicativo será algo como abaixo
<LanguageProvider>
<App>
<MyPage />
</App>
</LanguageProvider>
Minha página está tendo um componente para mudar o idioma
<MyPage>
<LanguageSwitcher/>
</MyPage>
LanguageSwitcher
nesta MyPage
necessidade de atualizar o contexto para mudar o idioma para 'jp' como abaixo
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;
Como posso atualizar o contexto de dentro do componente LanguageSwitcher?
javascript
reactjs
react-context
mshameer
fonte
fonte
Respostas:
Usando ganchos
Os ganchos foram introduzidos em 16.8.0, portanto, o código a seguir requer uma versão mínima de 16.8.0 (role para baixo para ver o exemplo de componentes de classe). CodeSandbox Demo
1. Definir o estado pai para contexto dinâmico
Em primeiro lugar, para ter um contexto dinâmico que possa ser passado aos consumidores, usarei o estado do pai. Isso garante que eu tenha uma única fonte de verdade. Por exemplo, meu aplicativo pai terá a seguinte aparência:
const App = () => { const [language, setLanguage] = useState("en"); const value = { language, setLanguage }; return ( ... ); };
o
language
é armazenado no estado. Passaremos amboslanguage
e a função settersetLanguage
via contexto posteriormente.2. Criação de um contexto
Em seguida, criei um contexto de linguagem como este:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Aqui estou definindo os padrões para
language
('en') e umsetLanguage
função que será enviada pelo provedor de contexto ao (s) consumidor (es). Esses são apenas padrões e irei fornecer seus valores ao usar o componente de provedor no paiApp
.Note o
LanguageContext
permanece o mesmo se você usar ganchos ou componentes baseados em classe.3. Criação de um consumidor de contexto
Para que o alternador de idioma defina o idioma, ele deve ter acesso à função configurador de idioma via contexto. Pode ser parecido com isto:
const LanguageSwitcher = () => { const { language, setLanguage } = useContext(LanguageContext); return ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> ); };
Aqui estou apenas definindo o idioma para 'jp', mas você pode ter sua própria lógica para definir os idiomas para isso.
4. Envolvendo o consumidor em um provedor
Agora, vou renderizar meu componente de alternador de idioma em a
LanguageContext.Provider
e passar os valores que devem ser enviados via contexto para qualquer nível mais profundo. É assim que meus pais seApp
parecem: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> ); };
Agora, sempre que o alternador de idioma é clicado, ele atualiza o contexto dinamicamente.
CodeSandbox Demo
Usando componentes de classe
A API de contexto mais recente foi introduzida no React 16.3, que fornece uma ótima maneira de ter um contexto dinâmico. O código a seguir requer uma versão mínima de 16.3.0. CodeSandbox Demo
1. Definir o estado pai para contexto dinâmico
Em primeiro lugar, para ter um contexto dinâmico que possa ser passado aos consumidores, usarei o estado do pai. Isso garante que eu tenha uma única fonte de verdade. Por exemplo, meu aplicativo pai terá a seguinte aparência:
class App extends Component { setLanguage = language => { this.setState({ language }); }; state = { language: "en", setLanguage: this.setLanguage }; ... }
O
language
é armazenado no estado junto com um método configurador de idioma, que você pode manter fora da árvore de estados.2. Criação de um contexto
Em seguida, criei um contexto de linguagem como este:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Aqui estou definindo os padrões para
language
('en') e umasetLanguage
função que será enviada pelo provedor de contexto ao (s) consumidor (es). Esses são apenas padrões e irei fornecer seus valores ao usar o componente de provedor no paiApp
.3. Criação de um consumidor de contexto
Para que o alternador de idioma defina o idioma, ele deve ter acesso à função configurador de idioma via contexto. Pode ser parecido com isto:
class LanguageSwitcher extends Component { render() { return ( <LanguageContext.Consumer> {({ language, setLanguage }) => ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> )} </LanguageContext.Consumer> ); } }
Aqui estou apenas definindo o idioma para 'jp', mas você pode ter sua própria lógica para definir os idiomas para isso.
4. Envolvendo o consumidor em um provedor
Agora, vou renderizar meu componente de alternador de idioma em a
LanguageContext.Provider
e passar os valores que devem ser enviados via contexto para qualquer nível mais profundo. É assim que meus pais seApp
parecem: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> ); } }
Agora, sempre que o alternador de idioma é clicado, ele atualiza o contexto dinamicamente.
CodeSandbox Demo
fonte
Provider
?value
, os padrões seriam utilizados pelo consumidor.setLanguage: (language: string) => {}
funciona para mim.A resposta de Maithani acima é uma ótima solução, mas é um componente de classe sem o uso de ganchos. Como o React recomenda o uso de componentes funcionais e ganchos , irei implementá-lo com os ganchos useContext e useState. Aqui está como você pode atualizar o contexto de um componente filho.
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
fonte
() => {}
state.setLanguage('pk')
não vai adiantar nada, já queconst state = useContext(LanguageContext)
está fora doLanguageContextProvider
. Resolvi meu problema movendo o provedor um nível acima e, em seguida, usandouseContext
em uma criança um nível abaixo.<LanguageContext.Consumer> {value => /* access your value here */} </LanguageContext.Consumer>
.Uma solução bastante simples é definir o estado em seu contexto, incluindo um método setState em seu provedor, assim:
return ( <Context.Provider value={{ state: this.state, updateLanguage: (returnVal) => { this.setState({ language: returnVal }) } }}> {this.props.children} </Context.Provider> )
E em seu consumidor, chame updateLanguage assim:
// 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>
fonte