我在上下文中有语言设置,如下所示
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
需要更新上下文,才能将语言更改为&#39; jp&#39;如下
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组件内部更新上下文?
答案 0 :(得分:36)
注意:我使用的是最新的context API,到目前为止,我使用的是React 16.3,它提供了一种具有动态上下文的好方法。 CodeSandbox Demo
首先,为了拥有可以传递给使用者的动态上下文,我将使用父级的状态。这样可以确保我拥有单一的真理来源。例如,我的父应用程序将如下所示:
class App extends Component {
setLanguage = language => {
this.setState({ language });
};
state = {
language: "en",
setLanguage: this.setLanguage
};
...
}
language
与语言设置器方法一起存储在状态中,您可以将其保留在状态树之外。
接下来,我创建了一个这样的语言上下文:
// set the defaults
const LanguageContext = React.createContext({
language: "en",
setLanguage: () => {}
});
在这里,我为language
('en')和setLanguage
函数设置了默认值,这些默认值将由上下文提供者发送给使用者。这些只是默认值,在父级App
中使用提供者组件时,我将提供它们的值。
为了让语言切换器设置语言,它应该可以通过上下文访问语言设置器功能。它可能看起来像这样:
class LanguageSwitcher extends Component {
render() {
return (
<LanguageContext.Consumer>
{({ language, setLanguage }) => (
<button onClick={() => setLanguage("jp")}>
Switch Language (Current: {language})
</button>
)}
</LanguageContext.Consumer>
);
}
}
在这里,我只是将语言设置为'jp',但是您可能有自己的逻辑来设置语言。
现在,我将在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>
);
}
}
现在,每当单击语言切换器时,它都会动态更新上下文。
答案 1 :(得分:28)
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
答案 2 :(得分:3)
一个非常简单的解决方案是通过在提供程序中包含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>
答案 3 :(得分:0)
我个人喜欢这种模式:
文件:context.jsx
DateFormat
然后你可以创建一个功能组件,如果它是提供者树中的一个孩子:
文件:component.jsx
def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(key=lambda t: t[0], reverse=reverse)
# ^^^^^^^^^^^^^^^^^^^^^^^
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
tv.heading(col,
command=lambda: treeview_sort_column(tv, col, not reverse))
root = Tk()
columns = ('name', 'number',)
treeview = ttk.Treeview(root, columns=columns, show='headings')
for t in (('one', '1'), ('ten', '10'), ('eleven', '11'), ('two', '2'), ('three', '3')):
treeview.insert('', END, values=(t[0],t[1]))
treeview.pack()
for col in columns:
treeview.heading(col, text=col,
command=lambda c=col: treeview_sort_column(treeview, c, False))
mainloop()