web-dev-qa-db-ja.com

useContextフックを使用するときにプロバイダー値にアクセスする方法

import React, { useContext } from 'react'
import { MyContext, MyProvider } from './Context'

const MasterContainer  = () =>{
    const ctx = useContext(MyContext)

    return (
        <MyProvider>
            {ctx}
            <MyContext.Consumer>
                {context=><div>{context.age}</div>}
            </MyContext.Consumer>  
        </MyProvider>
    )
}

export default MasterContainer

実際にctx.ageをプルしたいのですが、ctxは現在未定義を返しています。

import React from 'react'


export const MyContext = React.createContext("dude")

export class MyProvider extends React.Component{
    state = {
        name: 'Hello',
        age: 12
    }
    render(){
        return (
            <MyContext.Provider value={this.state}>
                {this.props.children}
            </MyContext.Provider>
        )
    }
}

基本的に、フックを使用してプロバイダーの状態の値にアクセスしたいのですが、どうすればよいですか?

3
Orca Prime

これは、createContext-メソッドと現在のコンテキスト値の更新の非常に単純な使用例です。 CodeSandbox-例

ここで重要なのは、 React.js createContext-メソッドのドキュメント で説明されているように、コンテキスト値はツリー内で最も一致するProviderに一致することです。

React.createContext-Contextオブジェクトを作成します。 ReactがこのContextオブジェクトにサブスクライブするコンポーネントをレンダリングすると、ツリー内でその上にある最も一致するプロバイダーから現在のコンテキスト値を読み取ります。

また、ドキュメントに記載されているように、デフォルト値の引数は、一致するプロバイダーが見つからない場合にのみ使用されることに注意してください。

DefaultValue引数は、コンポーネントのツリー内でその上に一致するプロバイダーがない場合にのみ使用されます。これは、コンポーネントをラップせずに個別にテストする場合に役立ちます。注:プロバイダー値としてundefinedを渡しても、消費コンポーネントがdefaultValueを使用することはありません。

4
Jimi Pajala

現在、React 16.7.0およびReactDOM16.7.0では、useContextが機能していないようです。機能コンポーネントの場合、これは私にとっては機能しました:

// Theme context, default to light theme
const ThemeContext = React.createContext('light');

// Signed-in user context
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
  render() {
    const {signedInUser, theme} = this.props;

    // App component that provides initial context values
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

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

// A component may consume multiple contexts
function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  );
}

クラスベースのコンポーネントの場合は、さらに簡単です。

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

class ThemedButton extends React.Component {
  render() {
    let props = this.props;
    let theme = this.context;
    return (
      <button
        {...props}
        style={{backgroundColor: theme.background}}
      />
    );
  }
}
ThemedButton.contextType = ThemeContext;

export default ThemedButton;

参照: https://reactjs.org/docs/context.html

0
Geocarlos