反应。如果对嵌套的 html 元素执行点击,组件的状态不会改变

ReactJS. The component's state won't change if click is performed on nested html element

所以,我有 IssuesList 组件,它是我使用 ajax 和 github api 和 DevStatus 得到的问题列表组件,将列表包装起来并包含所有逻辑,通过两个单选按钮等触发状态更改。

我的问题: 当我单击其中一个单选按钮时,如果单击的是单选按钮内的文本,DevStatus 组件将不会更改状态。当我点击单选按钮的角时,没有文本的蓝色区域,状态完全改变了。

单选按钮的结构如下:

  <div className="btn-group" data-toggle="buttons">

    <label className="btn btn-primary active"
           onClick={this.onChangeRadioButton.bind(this)}
           id={this.CLOSED_ISSUE_ID}>
      <input type="radio" name="options"
             autoComplete="off"
             id={this.CLOSED_ISSUE_INPT_ID}
             onChange={this.onInputChange.bind(this)} /> Closed Issues
    </label>

    <label className="btn btn-primary"
           onClick={this.onChangeRadioButton.bind(this)}
           id={this.OPEN_ISSUE_ID}>
      <input type="radio" name="options"
             autoComplete="off"
             id={this.OPENED_ISSUE_INPT_ID}
             onChange={this.onInputChange.bind(this)} /> Open Issues
    </label>

  </div>

这里是 codepen with the code and here's the full page view 这样你可以更好地理解我在说什么。

请打开完整页面视图并尝试单击包含文本的按钮部分和不包含文本的部分,您会注意到只要单击没有文本的部分 - 状态就会改变如果您单击文本本身 - 状态根本不会改变。


你能帮我解决这个问题吗?


PS:从 input 元素中删除 onChange 不是解决方案。

更新 1

如果您转到 DevTools 并检查 radiobutton 元素,您会看到 label 标记内有 input 和奇怪的 span 元素。 span 元素不在我写的代码中,是 React 自动添加的吗?由于某些原因,onClick 事件侦听器未应用于那些 inputspan 元素。

更新 2

我尝试将 click 事件监听器添加到开发工具控制台中的单选按钮,并试图找出被点击元素的目标。当我点击文本时 - 它是 span 元素,当我点击没有文本的地方时 - 它是 label 元素,这就是点击事件不起作用的原因。

能否使用 dangerouslySetInnerHTML 解决我的问题,以免产生不必要的 span

你能告诉我如何解决吗?

React 正在创建跨度,因为您的文本不在任何 div 中。如果有任何白色 space,它也会创建一个跨度(但在您的情况下,这是因为您的文本周围没有 div)。

但这里真正的问题是您检查事件的方式。 您需要检查 e.currentTarget 而不是 e.target

那就不用再用丑陋的dangerouslysetinnerhtml了!

React 似乎有时会在文本周围添加 span 标签,无论是否有空闲空格。 span 不允许在单击时触发 onClick 事件。

因此,要强制 React 不渲染 spans,可以使用 dangerouslySetInnerHTML

  noSpanRender(text) {
    return { __html: `<input type='radio' name='options' autoComplete='off'/>${text}` };
  }

  render() {
    return (
      <div className="dev-status-page col-centered">
        <div className="graphs">
          <h1 className="text-center page-header">
            Our Recent Closed and Opened Issues from GitHub
          </h1>
        </div>
        <div className="issues col-centered">
          <div className="btn-group" data-toggle="buttons">

            <label className="btn btn-primary active"
                   onClick={this.onChangeRadioButton.bind(this)}
                   id={this.CLOSED_ISSUE_ID}
                   dangerouslySetInnerHTML={this.noSpanRender('Closed Issues')} />

            <label className="btn btn-primary"
                   onClick={this.onChangeRadioButton.bind(this)}
                   id={this.OPEN_ISSUE_ID}
                   dangerouslySetInnerHTML={this.noSpanRender('Open Issues')} />

          </div>
          <IssuesList issues={this.state.issues} />
        </div>
      </div>
    )
  }

避免 input 标签内的那些 span 元素至关重要,因此使用 dangerouslySetInnerHTML 终于有所帮助。