"反应热装载机/巴别"打破我的构建 - 为什么需要它?

时间:2018-02-18 23:21:40

标签: reactjs webpack react-hot-loader

只要我将"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,一切正常,包括热重新加载。

所以,我的问题是:

  1. &#34; react-hot-loader / babel&#34;实际上呢?
  2. 如何将打破我的课程属性?
  3. 这是使用React 16.1,react-hot-loader 3,webpack 3.11,babel 6.x

    我的react-hot-loader/babel如果你想看到:

    .babelrc

2 个答案:

答案 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>