资讯专栏INFORMATION COLUMN

React context 丢失问题

Seay / 1250人阅读

摘要:丢失问题文本是为了说清目前的机制是而不是我们以为的机制,并说明这两者的区别。虽然明白了原理,但是问题并没有解决。上下文注意这里是,需要执行接受回调函数,回调函数中的内容为实测可以成功拿到。

React context 丢失问题
  

文本是为了说清react context目前的机制是owner context 而不是我们以为的parent context 机制,并说明这两者的区别。希望能对即将使用context的同学有所帮助.

什么是 context

context是为了解决component之间通信的上下文机制,该api目前并未定稿所以react并没有开放出来。最近有大量需要共享上下文的场景才去了解这个api,然后也成功被绕了进去....
介绍与用法这篇文章Introduction to Contexts in React.js说得很清楚~

问题场景

需要在Parent中声明context,在Children中拿到context并打印出来。

var Children = React.createClass({
  contextTypes: {
    value: React.PropTypes.string
  },
  render: function() {
    return 

{this.context.value || "并没有context"}
; } }); var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string }, getChildContext: function() { return { value: "上下文" }; }, render: function() { return (
{this.props.children}
); } }); var App = React.createClass({ render: function() { return ( ); } }); React.render(React.createElement(App), document.body);

这样执行完后屏幕上应该是『上下文』三个打字,但事实是

以及warning

那么问题来了,上下文为何失效了呢?!为什么Children拿不到Parent里面的context呢?!

find the problem

各种google之后发现gaearon大神在issue中的回复。

原来现在0.13.3版本的react context的传递规则是owner规则,在刚才的例子中虽然Children的parent为Parent,但是App才是Children与parent共同的owner,this.context只能拿到owner传递规则的context。

  

尼玛,跟想象中的不一样啊!你props、render的规则不都是Parent规则么!

不继续吐槽,那么按照这个思路把context放在App上,Parent与Children应该都能成功拿到Context了吧。

代码是这样的:

var Parent = React.createClass({
  contextTypes: {
    value: React.PropTypes.string
  },
  render: function() {
    return (


{this.context.value && "可算拿到了..." } {this.props.children}
); } }); var App = React.createClass({ childContextTypes: { value: React.PropTypes.string }, getChildContext: function() { return { value: "上下文" }; }, render: function() { return ( ); } }); React.render(React.createElement(App), document.body);

结果是这样的:

看来context成功被拿到,看到这里大家应该明白React context的机制了把。

how to get parent context

虽然明白了原理,但是问题并没有解决。我就是希望Chilren拿到Parent中的context,而不是拿到App中的context啊。我目前一共找到了两种方式可以在现阶段获取parent context。

1. use the callback

通过接收回调函数而不是react.element,然后在Parent中进行render,那么render的内容的owner自然就是Parent了,从而可以成功拿到Parent中的context。

var Parent = React.createClass({
  childContextTypes: {
    value: React.PropTypes.string
  },
  getChildContext: function() {
    return { value: "上下文" };
  },
  render: function() {
    return (


{this.props.children() /* 注意这里是function,需要执行 */}
); } }); // parent接受回调函数,回调函数中的内容owner为parent var App = React.createClass({ render: function() { return ( {this.renderChild} ); }, renderChild: function() { return ; } });

实测可以成功拿到context。

2.通过this._reactInternalInstance

这种方法虽然用起来很方便不过健壮性很差,等react更新之后没准又得改代码~
可以通过this._reactInternalInstance._context.value拿到该element的parent context。this._reactInternalInstance._currentElement._context.value就是默认的owner context。

var Children = React.createClass({
  contextTypes: {
    value: React.PropTypes.string
  },
  render: function() {
    return 

  • {"default context is: " + this.context.value}
  • {"parent context: " + this._reactInternalInstance._context.value}
  • {"owner context: " + this._reactInternalInstance._currentElement._context.value}
; } }); var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string }, getChildContext: function() { return { value: "parent" }; }, render: function() { return (
{this.props.children}
); } }); var App = React.createClass({ childContextTypes: { value: React.PropTypes.string }, getChildContext: function() { return { value: "app" }; }, render: function() { return ( ); }, }); React.render(React.createElement(App), document.body);

结果如下:

context es6 写法

由于同事问我es6下context怎么用,想到可能有些人也不清楚,在这里一并附上。个人不推荐使用es7语法。

import React from "react";

class Children extends React.Component {

  // 如果不需要在构造函数中使用可以不写,没有影响
  constructor(props, context) {
    super(props, context);
    console.log(context);
  }
  render() {
    return 

  • {"default context is: " + this.context.value}
  • {"parent context: " + this._reactInternalInstance._context.value}
  • {"owner context: " + this._reactInternalInstance._currentElement._context.value}
; } } Children.contextTypes = { value: React.PropTypes.string }; class Parent extends React.Component { getChildContext() { return { value: "parent" }; } render() { return (
{this.props.children}
); } } Parent.childContextTypes = { value: React.PropTypes.string }; class App extends React.Component { getChildContext() { return { value: "app" }; } render() { return ( ); } } App.childContextTypes = { value: React.PropTypes.string }; React.render(React.createElement(App), document.body);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85846.html

相关文章

  • react-dnd中context丢失解决方法

    摘要:等等这不就用的将的给覆盖了么这也很合理的解释了为啥会报错了。嗯还是拿不到,想起来了,虽然将静态属性拿了出来,但是原型方法不会拿出来啊,所以的就没用了,所以我们需要也将他拿出来,于是,加上一下代码这次总算拿到正确的结果了,开心 踩坑场景 在做业务的时候,有些模块是可以拖动的,恰好这些模块需要从根组件App的context上拿属性,同时App也是作为拖动上下文,被@DragDropCont...

    Arno 评论0 收藏0
  • 02.react进阶指南

    摘要:指定读取当前的。它为其后代元素触发额外的检查和警告。严格模式检查仅在开发模式下运行它们不会影响生产构建。作用识别不安全的生命周期关于使用过时字符串的警告关于使用废弃的方法的警告检测意外的副作用检测过时的为高阶组件。 react 进阶 懒加载 React.lazy函数能让你像渲染常规组件一样处理动态引入(的组件)。Suspense加载指示器为组件做优雅降级。fallback属性接受任何在...

    zzbo 评论0 收藏0
  • 电影天堂React Native 客户端V2.0发布

    摘要:电影天堂客户端重新开始具体更新以为准。重新开始两年前发布了第一个版本。最为一名偏体验偏设计的前端开发者,对界面和用户体验都有极高的重视。 电影天堂React Native 客户端 重新开始! 具体更新以https://github.com/XboxYan/DYTT为准。 重新开始 两年前发布了第一个版本。 现在, 使用最新的react-native 0.57和全新的设计完成了V2.0 ...

    MockingBird 评论0 收藏0
  • 探索 Redux4.0 版本迭代 论基础谈展望(对比 React context

    摘要:在几天前发布了新版本,被合入。但是在版本迭代的背后很多有趣的设计值得了解。参数处理这项改动由提出。对透明化处理中的,达到将包裹起来的目的。对的冻结认为,在中使用和方法是一种反模式。尤其是这样的新,某些开发者认为将逐渐取代。 showImg(https://segmentfault.com/img/remote/1460000014571148); Redux 在几天前(2018.04....

    xialong 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<