只要我将"react-hot-loader/babel"
添加到.babelrc
,它就会破坏我的React组件。
具体来说,我有一些看起来像这样的代码:
export default class Editor extends React.Component {
componentDidMount() {
console.log('this.canvas',this.canvas);
// ...
}
setRef = node => {
console.log('setRef');
this.canvas = node;
}
render() {
// tabIndex is needed to receive keyboard events -- https://stackoverflow.com/a/12887221/65387
return <canvas className={this.props.className} ref={this.setRef} tabIndex={0} />;
}
}
当我运行它时,我会在Chrome开发工具中看到这一点:
setRef
this.canvas undefined
这很奇怪,因为我们可以在致电this.canvas
之前看到它设置componentDidMount
,所以我不知道{{1}正在努力打破这一点。
没有react-hot-loader/babel
,一切正常,包括热重新加载。
所以,我的问题是:
这是使用React 16.1,react-hot-loader 3,webpack 3.11,babel 6.x
我的react-hot-loader/babel
如果你想看到:
.babelrc
答案 0 :(得分:1)
这似乎是react-hot-loader v3中的bug(我能够重现这个问题),并且在react-hot-loader v4中它是fixed。
根据this comment,这个问题似乎是由react-proxy中的代理逻辑引起的。一个技巧是存储一个对象以保存您的引用,这将通过react-proxy复制到代理,并将在this
的代理版本中提供:
export default class App extends React.Component {
constructor(props) {
super(props);
this.myRefs = {};
this.setRef = this.setRef.bind(this);
}
componentDidMount() {
console.log('componentDidMount',this.myRefs.div); // <-- Not null!
}
setRef(node) {
this.myRefs.div = node;
console.log('setRef',this.myRefs.div);
};
render() {
return <div ref={this.setRef}>test</div>
}
}
或者如next comment中所述,确保您的功能绑定在componentWillMount
中完成:
export default class App extends React.Component {
constructor(props) {
super(props);
// Do not bind here, "this" will get proxied.
}
// Proxy "this" is now available. Bind here.
componentWillMount() {
this.setRef = this.setRef.bind(this)
}
componentDidMount() {
console.log('componentDidMount',this.div); // <-- Not null!
}
setRef(node) {
this.div = node;
console.log('setRef',this.div);
};
render() {
return <div ref={this.setRef}>test</div>
}
}
我确实使用react-hot-loader v4验证了相关代码,并在那里修复了。
答案 1 :(得分:1)
PS:使用答案作为评论,因为我需要格式化
我能够重现这个问题。出现此问题的原因是热重新加载器会将代码更改为
setRef = (...params) => this.__setRef__REACT_HOT_LOADER__(...params)
然后在组件的prototype
__setRef__REACT_HOT_LOADER__(node) {
console.log("setRef called", this, node);
if (this === null) return;
if (node === null) return;
console.log(node);
this.div = node;
}
我认为打破this
链或这些副本会有所不同。有两处可以改变的地方
componentDidMount = () => {
console.log('componentDidMount',this.div);
}
如果您使用上述内容,那么它会起作用,因为它会变得相同。或者您需要将setRef更改为lambda
return <div ref={ node => this.div=node }>test</div>