When typing text into a contenteditable span in Safari or Firefox the caret moves to the start on each keypress. This only seems to happen when React re/renders the component.
Chrome works just fine. Haven't tested IE.
An example where |
is the caret and typing Hello
:
|
|H
|eH
|leH
|lleH
|olleH
Here's a simplified version of my component:
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;
Anyone come across this before?
You can achieve a contenteditable
by adding a handler to an HTML tag.
The problem is every time content is re-rendered the position of the cursor is reset. You are triggering a setState
when the content of the span
is edited, which is resetting the cursor position.
You could rather store a reference to the span
tag and update its value rather than triggering a state change.
A ref
could be stored which will inject the value in the span.
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>
);
}
}
Running code
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With