web-dev-qa-db-ja.com

コンシューマーからプロバイダーのコンテキスト値を更新する方法

MyContext.js

import React from "react";

const MyContext = React.createContext('test');
export default MyContext;

作成されたコンテキスト別のjsファイルで、親コンポーネントと子コンポーネントにアクセスできます

Parent.js

import MyContext from "./MyContext.js";
import Child from "./Child.js";

class Parent extends Component {

    constructor(props) {
      super(props);
      this.state = {
        Message: "Welcome React",
        ReturnMessage:""
      };
    }

    render() {
        return (
           <MyContext.Provider value={{state: this.state}}>      
              <Child /> 
           </MyContext.Provider>
       )
    }
}

そのため、プロバイダーコンテキストで親コンポーネントを作成し、プロバイダータブで子コンポーネントを呼び出します

Child.js

import MyContext from "./MyContext.js";

class Child extends Component {

    constructor(props) {
      super(props);
      this.state = {        
        ReturnMessage:""
      };
    }

    ClearData(context){
        this.setState({
           ReturnMessage:e.target.value
        });
        context.state.ReturnMessage = ReturnMessage
    }

    render() {
        return (
           <MyContext.Consumer>                 
              {(context) => <p>{context.state.Message}</p>}
              <input onChange={this.ClearData(context)} />
           </MyContext.Consumer>
       )
    }
}

そのため、コンシューマーを使用することで、子のレンダリング部分を表示できます。

私は、消費者からプロバイダーの状態に更新することに直面しています。

プロバイダーの状態を更新する方法またはプロバイダーの状態を操作する方法..

16
Nowshad Syed

まず、コンシューマーからコンテキストを更新するには、レンダリング関数の外部のコンテキストにアクセスする必要があります。これを行う方法の詳細については、

アクセスReactレンダリング関数外のコンテキスト

次に、プロバイダーからコンテキスト値を更新するハンドラーを提供し、それを直接変更しないでください。あなたのコードは次のようになります

Parent.js

import MyContext from "./MyContext.js";
import Child from "./Child.js";

class Parent extends Component {

    constructor(props) {
      super(props);
      this.state = {
        Message: "Welcome React",
        ReturnMessage:""
      };
    }

    updateValue = (key, val) => {
       this.setState({[key]: val});
    }
    render() {
        return (
           <MyContext.Provider value={{state: this.state, updateValue: this.updateValue}}>      
              <Child /> 
           </MyContext.Provider>
       )
    }
}

import MyContext from "./MyContext.js";

class Child extends Component {

    constructor(props) {
      super(props);
      this.state = {        
        ReturnMessage:""
      };
    }

    ClearData(e){
        const val = e.target.value;
        this.setState({
           ReturnMessage:val
        });
        this.props.context.updateValue('ReturnMessage', val);
    }

    render() {
        return (
           <React.Fragment>
             <p>{this.props.context.state.Message}</p>}
             <input onChange={this.ClearData} />
           </React.Fragment>
       )
    }
}

const withContext = (Component) => {
   return (props) => {
       <MyContext.Consumer>    
            {(context) => {
               return <Component {...props} context={context} />
            }}
       </MyContext.Consumer>
   }
}

export default withContext(Child);
12
Shubham Khatri

状態を更新するには、Providerコンポーネントで関数を作成する必要があります。正確に言えば、Consumerは、Providerコンポーネントで記述した値と関数のみを使用できます。

親コンポーネント内

updateReturnMessage = (ReturnMessage) => {
  this.setState((prevState) => ({ ...prevState, ReturnMessage }))
}

<MyContext.Provider value={{ state: this.state, updateReturnMessage: this.updateReturnMessage }}>
// your code goes here
</MyContext.Provider>

子コンポーネント内:

ClearData(e){
  const val = e.target.value;
  this.context.updateReturnMessage(val);
}

この関数は、Reduxおよびfluxで利用可能なaction creatorsに似ています

1

ネストされたコンポーネントからコンテキストを更新する

多くの場合、コンポーネントツリーのどこかに深くネストされているコンポーネントからコンテキストを更新する必要があります。この場合、コンテキストを介して関数を渡し、コンシューマがコンテキストを更新できるようにします。

theme-context.js

// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});

theme-toggler-button.js

import {ThemeContext} from './theme-context';

function ThemeTogglerButton() {
  // The Theme Toggler Button receives not only the theme
  // but also a toggleTheme function from the context
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button
          onClick={toggleTheme}
          style={{backgroundColor: theme.background}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

export default ThemeTogglerButton;

app.js

import {ThemeContext, themes} from './theme-context';
import ThemeTogglerButton from './theme-toggler-button';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggleTheme = () => {
      this.setState(state => ({
        theme:
          state.theme === themes.dark
            ? themes.light
            : themes.dark,
      }));
    };

    // State also contains the updater function so it will
    // be passed down into the context provider
    this.state = {
      theme: themes.light,
      toggleTheme: this.toggleTheme,
    };
  }

  render() {
    // The entire state is passed to the provider
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}

function Content() {
  return (
    <div>
      <ThemeTogglerButton />
    </div>
  );
}

ReactDOM.render(<App />, document.root);

上記の例は、React Context API docs v16.8.6から直接のものであり、消費者からコンテキスト値を更新するための推奨方法です。 https://reactjs.org/docs/context.html#updating-context-from-a-nested-component

1
Jack