I have simple component
class ContentEditable extends React.Component {
constructor(props) {
super(props);
this.handleInput = this.handleInput.bind(this);
}
handleInput(event) {
let html = event.target.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
this.props.onChange({ target: { value: html, name: this.props.name } });
this.lastHtml = html;
}
}
render() {
return (
<span
contentEditable="true"
onInput={this.handleInput}
className={"auto " + this.props.className}
dangerouslySetInnerHTML={{ __html: this.props.value }}
/>
);
}
}
export default ContentEditable;
<ContentEditable
value={this.state.name}
onChange={e => {
this.setState({ name: e.target.value });
}}
/>;
The component works but the cursor position never changes, it is always on first position instead after the rendered text.
I tested examples form this forum but it doesn't work for me.
I use React 15.6.1
and test it on chrome (Os X)
.
Any hint how I can solve this problem?
The solution with useRef
will be something look like below.
Here the useRef
will keep the default value / initial value apart from the component rendering cycles, so it will retain the original value without being affected by other kinds of operations we do in the react component.
This component does two things
onChange
methodprop
named value
and renders the value in the custom input box (that was created using contentEditable
)I have added a code sandbox, link here, use this to see how this works!
The code sandbox example contains two components
- one is
ContentEditableWithRef
which solves the problem withuseRef
, which is an uncontrolled component and- the other component is
ContentEditable
which usesuseState
to solve the same problem.
I also had same problem. Just fixed it with ref
. Just assign textContent
of event.target to ref
.
const textareaEl = useRef<HTMLDivElement>(null);
const handleChange = (e: React.ChangeEvent<HTMLDivElement>) => {
textareaEl.current.textContent = e.target.textContent;
onChange(e); // If you have change event for form/state
};
/** If you're passing value from state,
you can mutate it each change for not losing cursor position.
*/
useEffect(() => {
if (value) {
textareaEl.current.textContent = value;
}
}, [value]);
return (
<div
id="textarea-element"
ref={textareaEl}
contentEditable={true}
suppressContentEditableWarning={true}
onChange={handleChange}
/>
)
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