如何从子组件内部更新 React Context? [英] How to update React Context from inside a child component?

查看:91
本文介绍了如何从子组件内部更新 React Context?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在上下文中有语言设置,如下所示

class LanguageProvider 扩展组件 {静态 childContextTypes = {langConfig: PropTypes.object,};getChildContext() {返回 { langConfig: 'en' };}使成为() {返回 this.props.children;}}导出默认语言提供程序;

我的应用程序代码如下

<应用程序><我的页面/></应用程序></LanguageProvider>

我的页面有一个切换语言的组件

<语言切换器/></我的页面>

LanguageSwitcher 在这个 MyPage 中需要更新上下文以将语言更改为 'jp' 如下

class LanguageSwitcher 扩展组件 {静态上下文类型 = {langConfig: PropTypes.object,};更新语言(){//这里我需要将langConfig更新为'jp'}使成为() {return <button onClick={this.updateLanguage}>更改语言</button>;}}导出默认语言切换器;

如何从 LanguageSwitcher 组件内部更新上下文?

解决方案

使用钩子

Hooks 是在 16.8.0 中引入的,因此以下代码要求最低版本为 16.8.0(向下滚动查看类组件示例).CodeSandbox 演示

1.为动态上下文设置父状态

首先,为了有一个可以传递给消费者的动态上下文,我将使用父级的状态.这确保了我有一个单一的事实来源.例如,我的父应用程序将如下所示:

const App = () =>{const [language, setLanguage] = useState(en");const value = { 语言,setLanguage };返回 (...);};

language 存储在状态中.稍后我们将通过上下文传递 language 和 setter 函数 setLanguage.

2.创建上下文

接下来,我创建了这样的语言上下文:

//设置默认值const LanguageContext = React.createContext({语言:en",设置语言:() =>{}});

这里我设置了 language ('en') 和 setLanguage 函数的默认值,该函数将由上下文提供者发送给消费者.这些只是默认值,我将在父 App 中使用提供程序组件时提供它们的值.

注意:无论您使用钩子还是基于类的组件,LanguageContext 都保持不变.

3.创建上下文消费者

为了让语言切换器设置语言,它应该可以通过上下文访问语言设置器功能.它看起来像这样:

const LanguageSwitcher = () =>{const { 语言,setLanguage } = useContext(LanguageContext);返回 (<button onClick={() =>setLanguage(jp")}>切换语言(当前:{language}));};

这里我只是将语言设置为jp",但您可能有自己的逻辑来为此设置语言.

4.将消费者包装在提供者中

现在我将在 LanguageContext.Provider 中呈现我的语言切换器组件,并传入必须通过上下文发送到任何更深层次的值.这是我的父 App 的样子:

const App = () =>{const [language, setLanguage] = useState(en");const value = { 语言,setLanguage };返回 (<LanguageContext.Provider value={value}><h2>当前语言:{language}</h2><p>点击按钮更改为jp</p><div>{/* 可以嵌套 */}<语言切换器/>

</LanguageContext.Provider>);};

现在,每当点击语言切换器时,它都会动态更新上下文.

CodeSandbox 演示

使用类组件

最新的 context API 是在 React 16.3 中引入的,它提供了一种很好的方式来获得动态语境.以下代码要求最低版本为 16.3.0.CodeSandbox 演示

1.为动态上下文设置父状态

首先,为了有一个可以传递给消费者的动态上下文,我将使用父级的状态.这确保了我有一个单一的事实来源.例如,我的父应用程序将如下所示:

class App 扩展组件 {setLanguage = 语言 =>{this.setState({语言});};状态 = {语言:en",设置语言:this.setLanguage};...}

language 与语言设置器方法一起存储在状态中,您可以将其保存在状态树之外.

2.创建上下文

接下来,我创建了这样的语言上下文:

//设置默认值const LanguageContext = React.createContext({语言:en",设置语言:() =>{}});

这里我设置了 language ('en') 和 setLanguage 函数的默认值,该函数将由上下文提供者发送给消费者.这些只是默认值,我将在父 App 中使用提供程序组件时提供它们的值.

3.创建上下文消费者

为了让语言切换器设置语言,它应该可以通过上下文访问语言设置器功能.它看起来像这样:

class LanguageSwitcher 扩展组件 {使成为() {返回 (<LanguageContext.Consumer>{({ 语言,setLanguage }) =>(<button onClick={() =>setLanguage(jp")}>切换语言(当前:{language}))}</LanguageContext.Consumer>);}}

这里我只是将语言设置为jp",但您可能有自己的逻辑来为此设置语言.

4.将消费者包装在提供者中

现在我将在 LanguageContext.Provider 中呈现我的语言切换器组件,并传入必须通过上下文发送到任何更深层次的值.这是我的父 App 的样子:

class App 扩展组件 {setLanguage = 语言 =>{this.setState({语言});};状态 = {语言:en",设置语言:this.setLanguage};使成为() {返回 (<LanguageContext.Provider value={this.state}><h2>当前语言:{this.state.language}</h2><p>点击按钮更改为jp</p><div>{/* 可以嵌套 */}<语言切换器/>

</LanguageContext.Provider>);}}

现在,每当点击语言切换器时,它都会动态更新上下文.

CodeSandbox 演示

I have the language settings in the context as like below

class LanguageProvider extends Component {
  static childContextTypes = {
    langConfig: PropTypes.object,
  };

  getChildContext() {
    return { langConfig: 'en' };
  }

  render() {
    return this.props.children;
  }
}

export default LanguageProvider;

My application code will be something like below

<LanguageProvider>
  <App>
    <MyPage />
  </App>
</LanguageProvider>

My Page is having a component to switch the language

<MyPage>
  <LanguageSwitcher/>
</MyPage>

LanguageSwitcher in this MyPage need to update the context to change the language into 'jp' as below

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;

How can I update the context from inside the LanguageSwitcher component ?

解决方案

Using hooks

Hooks were introduced in 16.8.0 so the following code requires a minimum version of 16.8.0 (scroll down for the class components example). CodeSandbox Demo

1. Setting parent state for dynamic context

Firstly, in order to have a dynamic context which can be passed to the consumers, I'll use the parent's state. This ensures that I've a single source of truth going forth. For example, my parent App will look like this:

const App = () => {
  const [language, setLanguage] = useState("en");
  const value = { language, setLanguage };

  return (
    ...
  );
};

The language is stored in the state. We will pass both language and the setter function setLanguage via context later.

2. Creating a context

Next, I created a language context like this:

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

Here I'm setting the defaults for language ('en') and a setLanguage function which will be sent by the context provider to the consumer(s). These are only defaults and I'll provide their values when using the provider component in the parent App.

Note: the LanguageContext remains same whether you use hooks or class based components.

3. Creating a context consumer

In order to have the language switcher set the language, it should have the access to the language setter function via context. It can look something like this:

const LanguageSwitcher = () => {
  const { language, setLanguage } = useContext(LanguageContext);
  return (
    <button onClick={() => setLanguage("jp")}>
      Switch Language (Current: {language})
    </button>
  );
};

Here I'm just setting the language to 'jp' but you may have your own logic to set languages for this.

4. Wrapping the consumer in a provider

Now I'll render my language switcher component in a LanguageContext.Provider and pass in the values which have to be sent via context to any level deeper. Here's how my parent App look like:

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>
  );
};

Now, whenever the language switcher is clicked it updates the context dynamically.

CodeSandbox Demo

Using class components

The latest context API was introduced in React 16.3 which provides a great way of having a dynamic context. The following code requires a minimum version of 16.3.0. CodeSandbox Demo

1. Setting parent state for dynamic context

Firstly, in order to have a dynamic context which can be passed to the consumers, I'll use the parent's state. This ensures that I've a single source of truth going forth. For example, my parent App will look like this:

class App extends Component {
  setLanguage = language => {
    this.setState({ language });
  };

  state = {
    language: "en",
    setLanguage: this.setLanguage
  };

  ...
}

The language is stored in the state along with a language setter method, which you may keep outside the state tree.

2. Creating a context

Next, I created a language context like this:

// set the defaults
const LanguageContext = React.createContext({
  language: "en",
  setLanguage: () => {}
});

Here I'm setting the defaults for language ('en') and a setLanguage function which will be sent by the context provider to the consumer(s). These are only defaults and I'll provide their values when using the provider component in the parent App.

3. Creating a context consumer

In order to have the language switcher set the language, it should have the access to the language setter function via context. It can look something like this:

class LanguageSwitcher extends Component {
  render() {
    return (
      <LanguageContext.Consumer>
        {({ language, setLanguage }) => (
          <button onClick={() => setLanguage("jp")}>
            Switch Language (Current: {language})
          </button>
        )}
      </LanguageContext.Consumer>
    );
  }
}

Here I'm just setting the language to 'jp' but you may have your own logic to set languages for this.

4. Wrapping the consumer in a provider

Now I'll render my language switcher component in a LanguageContext.Provider and pass in the values which have to be sent via context to any level deeper. Here's how my parent App look like:

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>
    );
  }
}

Now, whenever the language switcher is clicked it updates the context dynamically.

CodeSandbox Demo

这篇关于如何从子组件内部更新 React Context?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆