【问题标题】:In React component lifecycle methods, `this.context` is an empty Object在 React 组件生命周期方法中,`this.context` 是一个空对象
【发布时间】:2019-03-28 18:45:45
【问题描述】:

为什么this.context 在这个 React 组件生命周期方法中是一个空对象?

该上下文在Consumer 中具有该上下文的正确值。只有this.context API 失败。

const LoremContext = React.createContext({
    lorem: "ipsum",
})


class MenuItem extends React.Component {

    componentDidMount() {
        console.log(
            "In MenuItem.componentDidMount, this.context is:",
            this.context)
    }

    render() {
        console.log(
            "In MenuItem.render, this.context is:",
            this.context)
        return ( <LoremContext.Consumer>{
            (lorem) => {
                console.log("In LoremContext.Consumer, lorem is:", lorem)
                return (
                    <li>
                        { `Eat ${this.props.dish} at ${lorem}` }
                    </li>
                )
            }
        }</LoremContext.Consumer> )
    }
}

MenuItem.contextType = LoremContext

class Menu extends React.Component {
    render() {
        …
    }
}

class Application extends React.Component {
    render() {
        return (
            <LoremContext.Provider value={ this.props.world.lorem }>
                <section className="app">
                    <Menu menuItems={ [ … ] } />
                <p>Fusce varius id arcu egestas sodales</p>
            </section>
        </LoremContext.Provider>
    )
}

ReactDOM.render(
    <Application world={ { lorem: "consecteur" } } />,
    document.getElementById('app-container'),
)

这是使用 React 16.4,因此它使用了 documented context API(在 React 16.3 中引入)。

根据文档化的 API,上面的代码应该可以通过两种方式访问​​上下文(在 React.createContext 的返回值中定义):

  • LoremContext.Consumer 组件接收LoremContext.Provider 传递的上下文值。

    然后消费者将该上下文值作为参数提供给该组件中的函数。在这种情况下,lorem 是接收上下文值的参数。

  • this.context 属性在“生命周期方法”内接收(由于 declared MenuItem.contextType class property)上下文值。

其中只有一个对我有用。

  • LoremContext.Consumer API 正在正确获取和传递上下文值。 console.log 输出为:
  In LoremContext.Consumer, lorem is: consecteur
  • this.context 没有获得正确的值,而是获得了一个空对象。 console.log 输出为:
  In MenuItem.render, context is: Object {  }
  In MenuItem.componentDidMount, context is: Object {  }

所以消费者收到了正确的值,但this.context 不是。为什么有区别?如何获得this.context 收到的正确值?

【问题讨论】:

标签: reactjs


【解决方案1】:

this.context 是在 React 16.6 中引入的,你看可以看here

在此版本之前,在您正在使用的16.4 上,可以实现在 React Lifecycles 中访问上下文:

class Button extends React.Component {
  componentDidMount() {
    // ThemeContext value is this.props.theme
  }

  componentDidUpdate(prevProps, prevState) {
    // Previous ThemeContext value is prevProps.theme
    // New ThemeContext value is this.props.theme
  }

  render() {
    const {theme, children} = this.props;
    return (
      <button className={theme || 'light'}>
        {children}
      </button>
    );
  }
}

export default props => (
  <ThemeContext.Consumer>
    {theme => <Button {...props} theme={theme} />}
  </ThemeContext.Consumer>
);

docs for more information

【讨论】:

  • “this.context 是在 React 16.6 中引入的”——好吧,废话。如果他们在文档中这样会更清楚,而不是对所有这些都是 16.3 中的新功能大肆宣传。谢谢。
  • 他们可以在某处使用新标签。但是运气不好,这是一两天前添加的
  • @bignose 我在这里看不到任何不一致之处。 React 文档涵盖了最后一个版本,截至目前为 16.6。上下文 API 是 16.3。上下文+上下文类型为 16.6。如果您需要知道特定功能的来源,可以从变更日志或reactjs.org/blog 中找到
【解决方案2】:

尝试在单独的文件中创建上下文,然后将其导入。这对我有用。当在使用&lt;MyContext.Provider&gt; 标签的同一文件中调用createContext 时,消费者只看到一个空对象。当我将createContext 移动到一个单独的文件时,消费者看到了预期值。这适用于两种消费方式 - &lt;MyContext.Consumer&gt;MyClass.contextType/this.context

恐怕我无法解释为什么这行得通,但我在this thread 中找到了解决方案。

【讨论】:

    【解决方案3】:

    不幸的是,目标组件中没有这部分,它是空的。

    static contextType = ThemeContext; // assign the correct context 
    

    在创建之前

    const ThemeContext = React.createContext('light');
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-10
      • 2020-02-14
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多