I get the following warning when rendering my component:
Warning: A component is
contentEditable
and containschildren
managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.
This is my component:
import React, { Component } from "react";
export default class Editable extends Component {
render() {
return (
<div contentEditable={true} onBlur={this.props.handleBlur}>
{this.props.children}
</div>
);
}
}
This component from https://github.com/lovasoa/react-contenteditable
does not generate the warning.
import React from 'react';
let stripNbsp = str => str.replace(/ |\u202F|\u00A0/g, ' ');
export default class ContentEditable extends React.Component {
constructor() {
super();
this.emitChange = this.emitChange.bind(this);
}
render() {
var { tagName, html, ...props } = this.props;
return React.createElement(
tagName || 'div',
{
...props,
ref: (e) => this.htmlEl = e,
onInput: this.emitChange,
onBlur: this.props.onBlur || this.emitChange,
contentEditable: !this.props.disabled,
dangerouslySetInnerHTML: {__html: html}
},
this.props.children);
}
shouldComponentUpdate(nextProps) {
let { props, htmlEl } = this;
// We need not rerender if the change of props simply reflects the user's edits.
// Rerendering in this case would make the cursor/caret jump
// Rerender if there is no element yet... (somehow?)
if (!htmlEl) {
return true;
}
// ...or if html really changed... (programmatically, not by user edit)
if (
stripNbsp(nextProps.html) !== stripNbsp(htmlEl.innerHTML) &&
nextProps.html !== props.html
) {
return true;
}
let optional = ['style', 'className', 'disabled', 'tagName'];
// Handle additional properties
return optional.some(name => props[name] !== nextProps[name]);
}
componentDidUpdate() {
if ( this.htmlEl && this.props.html !== this.htmlEl.innerHTML ) {
// Perhaps React (whose VDOM gets outdated because we often prevent
// rerendering) did not update the DOM. So we update it manually now.
this.htmlEl.innerHTML = this.props.html;
}
}
emitChange(evt) {
if (!this.htmlEl) return;
var html = this.htmlEl.innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
// Clone event with Object.assign to avoid
// "Cannot assign to read only property 'target' of object"
var evt = Object.assign({}, evt, {
target: {
value: html
}
});
this.props.onChange(evt);
}
this.lastHtml = html;
}
}
Questions:
https://reactjs.org/docs/dom-elements.html
.https://github.com/lovasoa/react-contenteditable
generate the same warning?The component you stated is generating component calling React.createElement
as follows
and thus avoiding the warning:
function ContentEditable(props) {
return React.createElement('div', {contentEditable: true});
}
Whereas you are using jsx.
function ContentEditable(props) {
return (<div contentEditable={true}></div>);
}
You can read more here about why react
warns you. If you want to suppress the warning you can also use
suppressContentEditableWarning
attribute.
function ContentEditable(props) {
return (<div contentEditable={true} suppressContentEditableWarning={true}></div>);
}
When you set contenteditable
you're letting the content be modified in the browser.
If you change the DOM without React managing behind, React will warn you as this might cause issues when, for example, updating those elements. You are passing {this.props.children}
which comes directly from React, using contenteditable
will let your content be modified by a user in the browser, thus will might not be the same as React has no control anymore.
You can use suppressContentEditableWarning={true}
to avoid that warning.
You either can use React.createElement
and pass an argument {contentEditable: true}
to avoid the warning (As like https://github.com/lovasoa/react-contenteditable is doing)
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