React Router context.router 未定义错误

我在使用 react-router@2.4.1 的时候用了 ES6 的 class 来构造 React 组件类,碰到一个坑:

class Example extends React.Component {
    constructor(props) {
        super(props);
        this.context.router; // undefined
        this.context.router.push('/'); // error
        props.history; // deprecated
    }
}

不得已只能用即将被抛弃的props.history.push(...) 来进行路由跳转,这样就相当不优雅了。

其他也有人碰到了这个问题,于是在react-router的GitHub上提了一个Issue #1059

听说要改成这样:

class Example extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.context.router; // it works
    }
}

Example.contextTypes = {
    router: React.PropsTypes.func.isRequired
}

真是让人感觉非常不优雅,控制台又打出了一行Warning,尽管真的 context.router 出现了。

我要报警了……还是算了,自己踩坑。


contextTypes 是React里面的一个类型验证的机制,用于验证 context 的属性的类型。

React 对 context 的态度是,只要没有在 contextTypes 中声明的属性一律不准加入 context,但没有通过类型验证的只会在控制台打出一行 Warning。

即,如果你不显式声明这个 contextTypes,React Router就没有办法在 context 中加入 router 对象,然后就会出现 this.context.router 未定义的现象。

那么,既然上面的 Example.contextTypes.router 已经声明了,为什么还会报Warning呢?

是因为没有通过contextTypes的验证。

实际上react-router 传进来的这个router对象是一个Object类型,然而react-router却要求是一个 function,自相矛盾。

大概是因为这个 2.4.1 版本自己有坑吧。在新版本与旧版本间狗带了。

那么我们来跳过这个验证:

class Example extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.context.router; // it works
    }
}

Example.contextTypes = {
    router: Object
}

OK,没有Warning 更没有 Error!
因为它本来就是一个Object嘛!

context 机制是 React 设计用来进行父子组件的通信用的,但是由于 Flux 的出现,父子组件都直接监听Store,改变Store就可以了。这个时候 context 的功能就变得有些鸡肋了。
这我不管,但是 React Router 用了 context,我既然用了 React Router 就要做好了解 context 来填坑的准备。


参考资料:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值