React组件constructor与componentDidMount中this指向不一致求助
我之前也碰到过这种constructor和componentDidMount里this指向不一致的诡异问题!结合你用的React 16.2.0、Webpack 3.10+TypeScript的技术栈,给你几个可能的排查方向:
装饰器或HOC的异常包装
如果你的组件使用了自定义装饰器或者第三方高阶组件(HOC),有些实现可能会在包装组件类时错误地篡改了实例创建逻辑,导致constructor和componentDidMount绑定的不是同一个实例。可以暂时移除装饰器/HOC,测试组件是否恢复正常。TypeScript或Webpack编译配置问题
老版本的ts-loader或者babel插件对类的编译可能存在兼容性bug:- 检查
tsconfig.json里的target选项,如果设置为ES5,可以尝试临时改成ES6看看是否解决(React 16.2对ES6类支持没问题); - 查看Webpack中
babel-loader的配置,是否开启了@babel/plugin-proposal-class-properties这类插件,且配置是否正确(比如是否设置了loose: true导致类属性编译异常)。
- 检查
全局代码污染
项目中的全局脚本或者第三方依赖可能修改了Function.prototype.bind、Object.create这类核心方法,干扰了React类组件的实例化过程。可以在constructor和componentDidMount中分别打印Object.getPrototypeOf(this),对比原型链是否一致,也可以检查全局对象上是否有异常的方法覆盖。组件被意外多次实例化
虽然概率不高,但可以在constructor里给实例加一个唯一标识(比如this.instanceId = Date.now() + Math.random()),然后在componentDidMount里打印这个标识,如果两次输出不一样,说明组件被创建了多个实例,可能是渲染逻辑里的问题(比如在循环中错误地每次都创建新组件)。
既然你在最小复现项目里是正常的,那问题肯定出在你项目的配置、依赖或者全局代码上,建议从上述方向逐步排查,先禁用非必要的插件/装饰器,再逐步恢复,应该能快速定位到原因。
内容的提问来源于stack exchange,提问作者ghost23

