使用 useContext 钩子时如何访问提供者值

How to access provider value when using useContext hook

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 现在正在返回 undefined 当我真的想拉 ctx.age

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

基本上我想使用挂钩访问我的提供者中的状态值,我该怎么做?

这是 createContext 方法和更新当前上下文值的一个非常简单的用例。 CodeSandbox-example

这里需要特别注意,如 React.js createContext-method documentation 中所述,上下文值将与树中最接近的匹配项 Provider 相匹配。

React.createContext - Creates an Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching Provider above it in the tree.

另外请记住,如文档中所述,默认值参数仅在未找到匹配的提供程序时使用。

The defaultValue argument is only used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing undefined as a Provider value does not cause consuming components to use defaultValue.

目前,在 React 16.7.0 和 ReactDOM 16.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>
  );
}

基于class的组件,就更简单了:

   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