React Router context.router 未定义错误

版权声明:CopyRight 2016, Heley Chen, Follow CC BY-NC-SA License https://blog.csdn.net/zccz14/article/details/51619587

我在使用 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 来填坑的准备。


参考资料:

阅读更多
换一批

没有更多推荐了,返回首页