反应"这个"在函数中始终为null

时间:2017-07-18 07:35:19

标签: javascript reactjs jsx

我有这门课。在所有函数中,除了Idea类中的render()之外,它等于null。 我试图从React.js: onChange event for contentEditable

重复解决方案



    
    class Idea extends React.Component {
    render() {
        return (
            <div id="root"
                 onInput={this.emitChange}
                 onBlur={this.emitChange}
                 contentEditable
                 dangerouslySetInnerHTML={{__html: this.props.html}}>
            </div>
        );
    }

    shouldComponentUpdate(nextProps) {
        return nextProps.html !== ReactDOM.findDOMNode(this).innerHTML;
    }

    componentDidUpdate() {
        if (this.props.html !== ReactDOM.findDOMNode(this).innerHTML) {
            ReactDOM.findDOMNode(this).innerHTML = this.props.html;
        }
    }

    emitChange() {
        var html = ReactDOM.findDOMNode(this).innerHTML;
        if (this.props.onChange && html !== this.lastHtml) {

            this.props.onChange({
                target: {
                    value: html
                }
            });
        }
        this.lastHtml = html;
    }
    }
&#13;
&#13;
&#13;

地图类:

&#13;
&#13;
    class Map extends React.Component {
    render() {
        var handleChange = function (event) {
            this.setState({html: event.target.value});
        }.bind(this);

        return (
            <div>
                <Header/>
                <div id="map">
                    {this.props.map.root && (
                        <Idea html={this.props.map.root.title} idea={this.props.map.root} onChange={handleChange}/>
                    )}
                </div>
            </div>
        );
    }
    }
&#13;
&#13;
&#13;

我不明白为什么这总是空的。你能帮助我吗? 感谢

4 个答案:

答案 0 :(得分:2)

您必须将此绑定到将在渲染功能中触发的函数。最好的方法是为组件添加构造函数(最佳做法是将其添加为第一个函数)。

class Idea extends React.Component {
  constructor(props) {
    super(props);
    this.emitChange = this.emitChange.bind(this);
  }
  ...
}

答案 1 :(得分:2)

您的代码中存在许多问题。首先,函数beacuse中没有this范围,您没有正确绑定它。您可以使用构造函数将this绑定到函数。这种绑定只会发生一次,这将避免重复绑定每个渲染内联绑定。

其次,(仅为了更好的练习)尽量避免使用dangerouslySetInnerHTML,因为React不会知道这些DOM节点,因此无法通过diffing提供更好的性能。并且避免在render中声明函数,这将在每次调用render时声明int。

class Idea extends React.Component {
constructor () {
 super();
 
 this.emitChange = (e) => this._emitChange(e);
}

render() {
    return (
        <div id="root"
             onInput={this.emitChange}
             onBlur={this.emitChange}
             contentEditable>
         {this.props.children}
        </div>
    );
}

shouldComponentUpdate(nextProps) {
    return nextProps.html !== ReactDOM.findDOMNode(this).innerHTML;
}

componentDidUpdate() {
    if (this.props.html !== ReactDOM.findDOMNode(this).innerHTML) {
        ReactDOM.findDOMNode(this).innerHTML = this.props.html;
    }
}

_emitChange() {
    var html = ReactDOM.findDOMNode(this).innerHTML;
    if (this.props.onChange && html !== this.lastHtml) {

        this.props.onChange({
            target: {
                value: html
            }
        });
    }
    this.lastHtml = html;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

class Map extends React.Component {
constructor () {
 super();
 
 this.handleChange = (e) => this._handleChange(e);
}
// i dont get why  do you store the event in state, if you dont use it.

_handleChange = function (event) {
    this.setState({html: event.target.value});
}

render() {
    return (
        <div>
            <Header/>
            <div id="map">
                {this.props.map.root && (
                    <Idea idea={this.props.map.root} onChange={this.handleChange}>
                    {this.props.map.root.title}
                    </Idea>
                )}
            </div>
        </div>
    );
}
}

答案 2 :(得分:1)

您在上面的代码段中有几个问题。

首先,你写了类似this.authenticationFactory的内容,然后onInput={this.emitChange}上下文将丢失 - 所以使用this操作或使用新的双冒号语法(在你的Babel预设集中支持它,比如https://gist.github.com/islahul/73f99302a721a714c002)。

其次,bind操作可以找到基础HTML元素。使用ref之类的内容,然后为React生命周期函数调用<div ref={elm => (this.componentRootDOM = elm)}></div>

答案 3 :(得分:1)

除了使用绑定方法之外,您还可以使用emitChange声明property initializer syntax,而不是使用绑定方法,基本上就是这样:

_emitChange = () => {
    var html = ReactDOM.findDOMNode(this).innerHTML;
    if (this.props.onChange && html !== this.lastHtml) {

        this.props.onChange({
            target: {
                value: html
            }
        });
    }
    this.lastHtml = html;
};

在这种情况下你只有一个方法来绑定任何一种方法都没问题,但是在你有更多方法的情况下,属性初始化器语法可能会在构造函数中保存一些膨胀