在 React 中更新状态时的问题

Problems when updating state in React

请查看我的 js fiddle 我在其中说明了问题

这是我的 js fiddle: https://jsfiddle.net/jajabya/fb93f7b0/

我的目标是获得一个 input 标签,其中可以通过包裹在 span 标签中来突出显示特殊词(例如日期或用户名)

div 肯定有问题,因为当我改用输入字段时一切正常。

我的问题是我无法使插入符号出现在正确的位置 每次状态更新 onInput

  onInput(event) {
    this.setState({
        html: event.target.innerText.toUpperCase()  
    });

  }

插入符号回滚到开头

我的想法是保存状态中的当前插入符号位置,并通过 componentDidUpdate() 中的 ref 将其设置回来(因为 ref 不会重新渲染组件)。

注意:这是一个原型想法,我从未进行过战斗测试,因此请谨慎使用。

插入符号位置代码取自以下答案:

  1. Code for getting the caret position

  2. Code for setting caret position

class Editable extends React.Component {
  componentDidUpdate(prev) {
    const { position } = this.props;
  
    if(position !== prev.position && this.ce.childNodes.length) {
      const range = document.createRange();
      const sel = window.getSelection();
      range.setStart(this.ce.childNodes[0], position);
      range.collapse(true);
      sel.removeAllRanges();
      sel.addRange(range);
    }
  }
  
  render() {
    return (
      <div
        contentEditable
        className={this.props.className}
        onInput={this.props.onInput}
        ref={ce => this.ce = ce}
        suppressContentEditableWarning>
        {this.props.html}
      </div>
    );
  }
}

class App extends React.Component {
  state = {
    html: 'Text',
    caret: 0
  };

  handleInput = (event) => this.setState({
    html: event.target.innerText.toUpperCase(),
    position: window.getSelection().getRangeAt(0).startOffset
  });
  
  render() {
    return (
     <Editable
        {...this.state}
        className="Editable"
        onInput={this.handleInput} />
    );
  }
}

ReactDOM.render(
  <App />,
  demo
);
<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>

<div id="demo"></div>