首页 文章

DOM上的手动innerHTML修改会停止ReactJS侦听器

提问于
浏览
0

我正在学习ReactJS和Node / Express生态系统(我的早期生活) . 我有一个基本的ReactJS文件,包括组件定义和渲染调用 . 它可以按预期工作 . 为了便于快速调试,昨天我在客户端代码中进行了以下更改:

// Added HTML id to body tag, no other changes whatsoever to DOM/HTML
<body id='body'>...</body>

// In client code, added:
document.getElementById('body').innerHTML += xhr.responseText;

xhr 是经过验证的功能性xmlHttpRequest() . 我发出请求,得到一个响应,并按预期呈现给身体 . 但是,这会阻止所有ReactJS组件监听其按钮并按定义触发其处理程序 . 没有控制台反馈或其他任何错误的迹象,ReactJS只是按预期进行第一次渲染,然后默默地停止响应 .

如果我注释掉单行 document.getEle... 那么一切都会重新开始,包括React和 xhr 本身 .

我知道在ReactJS中,范例不是以这种方式修改DOM,但我不明白为什么这一行会破坏所有ReactJS功能 . 对于上下文,这是我的代码的一部分:

This component appears to be fine with or without document.getEle... commented out.

// Hello World component: manage cookies and display a simple prop
var HelloWorldComponent = React.createClass({

  componentWillMount: function() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if( xhr.readyState == 4 && xhr.status == 200 ) {
        // NOTE: this `console.log` gives expected result regardless
        console.log('Performed initial cookie check.  Got response: ' + xhr.responseText);
        // document.getElementById('body').innerHTML += '<div>'+xhr.responseText+'</div>';
      }
      else {
        console.log('Tried initial cookie check.  Got HTTP response status: ' + xhr.status);
      }
    }
    xhr.open('POST', '/cookieCheck');
    xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
    xhr.send();
  },

  render: function() {
    return (
      <h1 id='italic-id' className='red-class'>Hello, {this.props.name}!</h1>
    );
  }
});

This component breaks unless document.getEle... is commented out, other wise it works perfectly.

// State component to display simple state
var StateComponent = React.createClass({

  // ReactJS Event: this fails with `document.getEle...` appearing elsewhere in the code
  incrementCount: function() {
    this.setState({
      count: this.state.count + 1
    });
  },

  getInitialState: function() {
    return {
      count: 0
    }
  },

  render: function() {
    return (
      <div className='increment-component'>
        <h3 className='red-class'>Count: {this.state.count}.</h3>
        <button onClick={this.incrementCount}>Boing!</button>
      </div>
    );
  }
});

Here's how I render my components:

ReactDOM.render(
  <StateComponent/>,
  document.getElementById('state-point')
);
// similar calls for other components as needed

对于's worth, I'已经尝试了 document.getEle... 作为第一个JS被解雇,正如最后一个JS被解雇,并且你现在看到它作为ReactJS组件的一部分 . 无论我把它放在代码中的哪个位置,结果都是一样的 .

1 回答

  • 2

    我相信原因是由于 innerHTML 如何运作 . 它完全重新解析和替换子DOM节点(即使你使用=只是追加新的节点),所以它会破坏以前附加到那些DOM节点的所有事件处理程序,在你的情况下是由React的DOM子树"managed" . 对于您的情况,您可能需要考虑使用 insertAdjacentHTML .

    来自MDN文档(https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML):

    “它不会重新解析它正在使用的元素,因此它不会破坏元素中的现有元素 . ”

    尝试使用以下内容:

    document.getElementById('body').insertAdjacentHTML('beforeend', xhr.responseText);
    

相关问题