Saya memiliki pengaturan bahasa dalam konteks seperti di bawah ini
class LanguageProvider extends Component {
static childContextTypes = {
langConfig: PropTypes.object,
};
getChildContext() {
return { langConfig: 'en' };
}
render() {
return this.props.children;
}
}
export default LanguageProvider;
Kode lamaran saya akan menjadi seperti di bawah ini
<LanguageProvider>
<App>
<MyPage />
</App>
</LanguageProvider>
Halaman Saya memiliki komponen untuk mengganti bahasa
<MyPage>
<LanguageSwitcher/>
</MyPage>
LanguageSwitcher
dalam hal ini MyPage
perlu memperbarui konteks untuk mengubah bahasa menjadi 'jp' seperti di bawah ini
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;
Bagaimana cara memperbarui konteks dari dalam komponen LanguageSwitcher?
javascript
reactjs
react-context
mshameer
sumber
sumber
Jawaban:
Menggunakan pengait
Hooks diperkenalkan di 16.8.0 sehingga kode berikut memerlukan versi minimum 16.8.0 (gulir ke bawah untuk contoh komponen kelas). Demo CodeSandbox
1. Menyetel status induk untuk konteks dinamis
Pertama, agar memiliki konteks dinamis yang dapat diteruskan ke konsumen, saya akan menggunakan status induk. Ini memastikan bahwa saya memiliki satu sumber kebenaran yang muncul. Misalnya, Aplikasi orang tua saya akan terlihat seperti ini:
const App = () => { const [language, setLanguage] = useState("en"); const value = { language, setLanguage }; return ( ... ); };
The
language
disimpan di negara bagian. Kami akan melewatkan keduanyalanguage
dan fungsi penyetelsetLanguage
melalui konteks nanti.2. Menciptakan konteks
Selanjutnya, saya membuat konteks bahasa seperti ini:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Di sini saya menyetel default untuk
language
('en') dansetLanguage
fungsi yang akan dikirim oleh penyedia konteks ke konsumen. Ini hanya default dan saya akan memberikan nilainya saat menggunakan komponen provider di indukApp
.Catatan:
LanguageContext
tetap sama apakah Anda3. Menciptakan konsumen konteks
Agar pengalih bahasa mengatur bahasa, ia harus memiliki akses ke fungsi penyetel bahasa melalui konteks. Ini bisa terlihat seperti ini:
const LanguageSwitcher = () => { const { language, setLanguage } = useContext(LanguageContext); return ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> ); };
Di sini saya hanya mengatur bahasa ke 'jp' tetapi Anda mungkin memiliki logika Anda sendiri untuk mengatur bahasa untuk ini.
4. Membungkus konsumen dalam penyedia
Sekarang saya akan membuat komponen pengalih bahasa saya di a
LanguageContext.Provider
dan meneruskan nilai-nilai yang harus dikirim melalui konteks ke tingkat yang lebih dalam. BeginiApp
penampilan orang tua saya :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> ); };
Sekarang, setiap kali pengalih bahasa diklik itu memperbarui konteks secara dinamis.
Demo CodeSandbox
Menggunakan komponen kelas
API konteks terbaru diperkenalkan di React 16.3 yang menyediakan cara yang bagus untuk memiliki konteks dinamis. Kode berikut membutuhkan versi minimum 16.3.0. Demo CodeSandbox
1. Menyetel status induk untuk konteks dinamis
Pertama, agar memiliki konteks dinamis yang dapat diteruskan ke konsumen, saya akan menggunakan status induk. Ini memastikan bahwa saya memiliki satu sumber kebenaran yang muncul. Misalnya, Aplikasi orang tua saya akan terlihat seperti ini:
class App extends Component { setLanguage = language => { this.setState({ language }); }; state = { language: "en", setLanguage: this.setLanguage }; ... }
Itu
language
disimpan di negara bagian bersama dengan metode penyetel bahasa, yang mungkin Anda simpan di luar pohon negara.2. Menciptakan konteks
Selanjutnya, saya membuat konteks bahasa seperti ini:
// set the defaults const LanguageContext = React.createContext({ language: "en", setLanguage: () => {} });
Di sini saya menyetel default untuk
language
('en') dansetLanguage
fungsi yang akan dikirim oleh penyedia konteks ke konsumen. Ini hanya default dan saya akan memberikan nilainya saat menggunakan komponen provider di indukApp
.3. Menciptakan konsumen konteks
Agar pengalih bahasa mengatur bahasa, ia harus memiliki akses ke fungsi penyetel bahasa melalui konteks. Ini bisa terlihat seperti ini:
class LanguageSwitcher extends Component { render() { return ( <LanguageContext.Consumer> {({ language, setLanguage }) => ( <button onClick={() => setLanguage("jp")}> Switch Language (Current: {language}) </button> )} </LanguageContext.Consumer> ); } }
Di sini saya hanya mengatur bahasa ke 'jp' tetapi Anda mungkin memiliki logika Anda sendiri untuk mengatur bahasa untuk ini.
4. Membungkus konsumen dalam penyedia
Sekarang saya akan membuat komponen pengalih bahasa saya di a
LanguageContext.Provider
dan meneruskan nilai-nilai yang harus dikirim melalui konteks ke tingkat yang lebih dalam. BeginiApp
penampilan orang tua saya :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> ); } }
Sekarang, setiap kali pengalih bahasa diklik itu memperbarui konteks secara dinamis.
Demo CodeSandbox
sumber
Provider
?value
, default akan digunakan oleh konsumen.setLanguage: (language: string) => {}
bekerja untuk saya.Jawaban di atas oleh Maithani adalah solusi yang bagus tetapi itu adalah komponen kelas tanpa menggunakan pengait. Karena direkomendasikan oleh React untuk menggunakan komponen fungsional dan hook jadi saya akan mengimplementasikannya dengan hook useContext dan useState. Berikut adalah bagaimana Anda bisa memperbarui konteks dari dalam komponen anak.
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
sumber
() => {}
state.setLanguage('pk')
tidak akan melakukan apa-apa, karenaconst state = useContext(LanguageContext)
berada di luarLanguageContextProvider
. Saya memecahkan masalah saya dengan memindahkan penyedia satu tingkat ke atas dan kemudian menggunakanuseContext
pada anak satu tingkat di bawah.<LanguageContext.Consumer> {value => /* access your value here */} </LanguageContext.Consumer>
.Salah satu solusi yang cukup sederhana adalah menyetel status pada konteks Anda dengan menyertakan metode setState di penyedia Anda seperti:
return ( <Context.Provider value={{ state: this.state, updateLanguage: (returnVal) => { this.setState({ language: returnVal }) } }}> {this.props.children} </Context.Provider> )
Dan di konsumen Anda, panggil updateLanguage seperti ini:
// 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>
sumber