在Safari和Firefox的React中重新渲染时,插入符号位置恢复为contenteditable span的开始

在Safari和Firefox的React中重新渲染时,插入符号位置恢复为contenteditable span的开始,firefox,reactjs,safari,contenteditable,caret,Firefox,Reactjs,Safari,Contenteditable,Caret,在Safari或Firefox中将文本键入可编辑的内容范围时,插入符号会在每次按键时移到起始位置。这似乎只有在React重新/渲染组件时才会发生 Chrome很好用。我还没有测试过IE 例如,|是插入符号并键入Hello: ||H|eH|leH| lleH|olleH 以下是我的组件的简化版本: import React, { Component } from 'react'; class ContentEditable extends Component { constructor

在Safari或Firefox中将文本键入可编辑的内容范围时,插入符号会在每次按键时移到起始位置。这似乎只有在React重新/渲染组件时才会发生

Chrome很好用。我还没有测试过IE


例如,
|
是插入符号并键入
Hello

|
|H
|eH
|leH
| lleH
|olleH

以下是我的组件的简化版本:

import React, { Component } from 'react';

class ContentEditable extends Component {
    constructor(props) {
        super(props);

        this.state = {
            value: props.value
        };
    }

    createMarkup() {
        return { __html: this.state.value };
    }

    handleInput(event) {
        this.setState({
            value: event.target.innerText
        });
    }

    isValid() {
        let bestLength = 3;

        return this.state.value.length > bestLength;
    }

    render() {
        let className = '';
        if (this.isValid()) {
            className = 'is-valid';
        }

        return (
            <span
                contentEditable="true"
                onInput={ this.handleInput.bind(this) }
                className={ className }
                dangerouslySetInnerHTML={ this.createMarkup() }
            >
            </span>
        );
    }
}

ContentEditable.propTypes = {
    value: React.PropTypes.string.isRequired
};

export default ContentEditable;
import React,{Component}来自'React';
类ContentEditable扩展组件{
建造师(道具){
超级(道具);
此.state={
价值:道具价值
};
}
createMarkup(){
返回{uuuhtml:this.state.value};
}
handleInput(事件){
这是我的国家({
值:event.target.innerText
});
}
isValid(){
设bestLength=3;
返回this.state.value.length>bestLength;
}
render(){
让className='';
if(this.isValid()){
className='是有效的';
}
返回(
);
}
}
ContentEditable.propTypes={
值:React.PropTypes.string.isRequired
};
导出默认内容可编辑;

以前有人遇到过这种情况吗?

您可以通过向HTML标记添加处理程序来实现可编辑的内容。 问题是每次重新呈现内容时,光标的位置都会重置。编辑
span
的内容时,将触发
setState
,这将重置光标位置

您可以存储对
span
标记的引用并更新其值,而不是触发状态更改

可以存储一个
ref
,将值注入量程

class ContentEditable extends Component {
  constructor(props) {
    super(props);
    this.spanRef = React.createRef();
    this.val = props.value;
  }

  handleInput(event) {
    const { innerText } = event.target;
    if (this.val !== innerText) {
      this.spanRef.innerText = innerText;
      this.val = innerText;
    }
  }

  render() {
    return (
      <span
        contentEditable="true"
        className={"is-valid"}
        onInput={this.handleInput.bind(this)}
        ref={this.spanRef}
        suppressContentEditableWarning={true}
      >
        {this.val}
      </span>
    );
  }
}
类内容可编辑扩展组件{
建造师(道具){
超级(道具);
this.spanRef=React.createRef();
this.val=props.value;
}
handleInput(事件){
const{innerText}=event.target;
if(this.val!==innerText){
this.spanRef.innerText=innerText;
this.val=内部文本;
}
}
render(){
返回(
{this.val}
);
}
}

edit:发生在Safari和Firefox中,而不是在Chrome.Hmmm中,很有趣。刚刚在Firefox中尝试了你的例子,我明白了这个问题。当我在字段开头键入时,插入符号移动到该字段的开头。我在OSX上。Firefox 48.0.2和Safari 10.0.1[编辑:啊,好的。谢谢你创建了演示!]在这里查看一些答案:你是如何解决这个问题的?有解决方案吗?请分享,我有类似的问题