DangerouslySetInnerHtml not updating during render

So, I created a component to include content editing components in my application. I copied this from some kind of essence, I believe, and then edited what I need.

The code is below. When I edit it, it launches the parent updates just fine, but when I try to set props.html in the parent, it is not reflected in the user interface. NEXT, console.log shows that this.props.html is equal to the empty string, but the user interface does not update and supports the text that was originally there.

I don’t understand how this is possible ... dangerouslySetInnerHtml = {__html: ''} has to make the user interface display an empty string ... it looks like it should be impossible to show old text for it.

var React = require('react'); var ContentEditable = React.createClass({ render: function(){ //TODO: find where html=undefined and fix it! So I can remove this? Maybe I should keep this safety. var html = this.props.html || ''; console.log('content editable render, html: ', this.props.html); return <div id="contenteditable" onInput={this.emitChange} onBlur={this.emitChange} contentEditable dangerouslySetInnerHTML={{__html: html}}></div>; }, shouldComponentUpdate: function(nextProps){ return nextProps.html !== this.getDOMNode().innerHTML; }, emitChange: function(){ var html = this.getDOMNode().innerHTML; if (this.props.onChange && html !== this.lastHtml) { this.props.onChange({ target: { value: html } }); } this.lastHtml = html; } }); module.exports = ContentEditable; 

(A bit of background, I'm trying to clear my input after sending it to save. Cleaning does not work, hence this question.)

+5
source share
4 answers

I had a very similar problem using contentEditable and shouldComponentUpdate , it seems that when resetting innerHTML with the same previous value, an error occurs using the dangerouslySetInnerHTML (or prop) function (I think that it does not work even if you paste the code without using him) ... I suspect (it's just an idea) that React compares the last value set through dangerouslySetInnerHTML with the new one you are trying to send, and decides not to update because it is the same (even if the real innerHTML was changed from for user interactions since these interactions do not trigger a state or props update for React).

Solution: The easiest solution I found was to reuse a different key every time I need it. for example, using key={Date()} .

Example: Here you can find your code (I changed part of it to make it work) when you type '?' in a div, the text inside the ContentEditable component should become an empty string (i.e. ''), it only works once, the second time you enter '?' will not work because innerHTML for the reaction will be the same as the one you set (i.e. an empty string so that it does not update the component).

And here , I added key={Date()} (this is the easiest way to show you that this work, but this is not the best way to set a unique key each time you re-render) to the editable component, now you can enter any number "? " and it will work.

+1
source

I found another solution, which is probably better than random key generation. Entering a key specifically in a div that calls #dangerouslySetInnerHtml, and not just on the component itself

 <div class='wrapper'> <div key={this.props.thing.id} dangerouslySetInnerHtml={this.props.thing.content} /> </div> 
0
source

I ran into the same problem (React 16) and used the approach suggested by MLR , which is to discard dangerouslySetInnerHTML and use componentDidMount() instead of the initial render and componentDidUpdate() for any subsequent renderings.

The solution here is adapted to React 16: https://codepen.io/mlbrgl/pen/PQdLgb

These interceptors will perform the same update, directly updating innerHTML from the props:

 componentDidMount() { this.updateInnerHTMLFromProps(); } componentDidUpdate() { this.updateInnerHTMLFromProps(); } updateInnerHTMLFromProps() { this.refEl.innerHTML = this.props.html; } 

It makes it clearer (at least for me) to see what is really happening without having the false expectation that dangerouslySetInnerHTML will support the DOM synchronously under any circumstances, as suggested by Mike Woodcock here fooobar.com/questions/1220643/ .. ..

For a full overview of the problem and both of the solutions outlined here, please check https://codepen.io/mlbrgl/pen/QQVMRP .

0
source

My (very simple) React app (version 16): it has contentEditable <div> . It successfully re-displays this <div> when the click button progresses. Instead of dangerouslySetInnerHtml I used ref={el => this.myRefElem = el} with componentWillUpdate(nextProps) { this.myRefElem.innerHTML = nextProps.myInputText; } componentWillUpdate(nextProps) { this.myRefElem.innerHTML = nextProps.myInputText; } For me, nextProps was important for the right value for re-rendering. See my project project files for the rest of the required code. CLICK HERE to see my React app. He has a button for loading project files (development mode). It (basically) only has an index.js file. - - - This application was initiated by mlbrgl , which asked me to use an alternative method.

0
source

All Articles