Tengo la configuración de idioma en el contexto como se muestra a continuación
class LanguageProvider extends Component {
static childContextTypes = {
langConfig: PropTypes.object,
};
getChildContext() {
return { langConfig: 'en' };
}
render() {
return this.props.children;
}
}
export default LanguageProvider;
El código de mi aplicación será algo como el siguiente
<LanguageProvider>
<App>
<MyPage />
</App>
</LanguageProvider>
Mi página tiene un componente para cambiar el idioma
<MyPage>
<LanguageSwitcher/>
</MyPage>
LanguageSwitcher
en esta MyPage
necesidad de actualizar el contexto para cambiar el idioma a 'jp' como se muestra a continuación
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;
¿Cómo puedo actualizar el contexto desde dentro del componente LanguageSwitcher?
javascript
reactjs
react-context
mshameer
fuente
fuente
Respuestas:
Usando ganchos
Los ganchos se introdujeron en 16.8.0, por lo que el siguiente código requiere una versión mínima de 16.8.0 (desplácese hacia abajo para ver el ejemplo de componentes de clase). Demostración de CodeSandbox
1. Establecer el estado principal para el contexto dinámico
En primer lugar, para tener un contexto dinámico que se pueda pasar a los consumidores, usaré el estado del padre. Esto asegura que tengo una única fuente de verdad. Por ejemplo, mi aplicación principal se verá así:
const App = () => { const [language, setLanguage] = useState("en"); const value = { language, setLanguage }; return ( ... ); };
Se
language
almacena en el estado. Pasaremos amboslanguage
y la función setter asetLanguage
través del contexto más adelante.2. Crear un contexto
A continuación, creé un contexto de lenguaje como este:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Aquí estoy configurando los valores predeterminados para
language
('en') y unasetLanguage
función que será enviada por el proveedor de contexto a los consumidores. Estos son solo valores predeterminados y proporcionaré sus valores cuando use el componente de proveedor en el padreApp
.Nota: lo
LanguageContext
mismo sigue siendo si3. Crear un consumidor de contexto
Para que el selector de idioma configure el idioma, debe tener acceso a la función de configuración de idioma a través del contexto. Puede verse algo como esto:
const LanguageSwitcher = () => { const { language, setLanguage } = useContext(LanguageContext); return ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> ); };
Aquí solo estoy configurando el idioma en 'jp', pero es posible que tenga su propia lógica para configurar los idiomas para esto.
4. Envolviendo al consumidor en un proveedor
Ahora renderizaré mi componente de cambio de idioma en ay pasaré
LanguageContext.Provider
los valores que deben enviarse a través del contexto a cualquier nivel más profundo. Así es como seApp
ve mi padre :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> ); };
Ahora, cada vez que se hace clic en el conmutador de idioma, se actualiza el contexto de forma dinámica.
Demostración de CodeSandbox
Usando componentes de clase
La última API de contexto se introdujo en React 16.3, que proporciona una excelente manera de tener un contexto dinámico. El siguiente código requiere una versión mínima de 16.3.0. Demostración de CodeSandbox
1. Establecer el estado principal para el contexto dinámico
En primer lugar, para tener un contexto dinámico que se pueda pasar a los consumidores, usaré el estado del padre. Esto asegura que tengo una única fuente de verdad. Por ejemplo, mi aplicación principal se verá así:
class App extends Component { setLanguage = language => { this.setState({ language }); }; state = { language: "en", setLanguage: this.setLanguage }; ... }
El
language
se almacena en el estado junto con un método de establecimiento de idioma, que puede mantener fuera del árbol de estado.2. Crear un contexto
A continuación, creé un contexto de lenguaje como este:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Aquí estoy configurando los valores predeterminados para
language
('en') y unasetLanguage
función que será enviada por el proveedor de contexto a los consumidores. Estos son solo valores predeterminados y proporcionaré sus valores cuando use el componente de proveedor en el padreApp
.3. Crear un consumidor de contexto
Para que el selector de idioma configure el idioma, debe tener acceso a la función de configuración de idioma a través del contexto. Puede verse algo como esto:
class LanguageSwitcher extends Component { render() { return ( <LanguageContext.Consumer> {({ language, setLanguage }) => ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> )} </LanguageContext.Consumer> ); } }
Aquí solo estoy configurando el idioma en 'jp', pero es posible que tenga su propia lógica para configurar los idiomas para esto.
4. Envolviendo al consumidor en un proveedor
Ahora renderizaré mi componente de cambio de idioma en ay pasaré
LanguageContext.Provider
los valores que deben enviarse a través del contexto a cualquier nivel más profundo. Así es como seApp
ve mi padre :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> ); } }
Ahora, cada vez que se hace clic en el conmutador de idioma, se actualiza el contexto de forma dinámica.
Demostración de CodeSandbox
fuente
Provider
?value
, el consumidor utilizará los valores predeterminados.setLanguage: (language: string) => {}
funciona para mi.La respuesta anterior de Maithani es una gran solución, pero es un componente de clase sin el uso de ganchos. Dado que React recomienda el uso de componentes funcionales y ganchos, lo implementaré con los ganchos useContext y useState. Así es como puede actualizar el contexto desde un componente secundario.
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
fuente
() => {}
state.setLanguage('pk')
no haré nada, ya queconst state = useContext(LanguageContext)
está fuera delLanguageContextProvider
. Resolví mi problema moviendo el proveedor un nivel hacia arriba y luego usándolouseContext
en un niño un nivel por debajo.<LanguageContext.Consumer> {value => /* access your value here */} </LanguageContext.Consumer>
.Una solución bastante simple es establecer el estado en su contexto incluyendo un método setState en su proveedor así:
return ( <Context.Provider value={{ state: this.state, updateLanguage: (returnVal) => { this.setState({ language: returnVal }) } }}> {this.props.children} </Context.Provider> )
Y en su consumidor, llame a updateLanguage así:
// 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>
fuente