3

I have a function where i want to return some HTML but when I call the function, or log it, it returns the variable as undefined:

  contentForRender = () => {
    const el = (
      <div><span>Lorem Ipsum</span></div>
    );
    return el;
  }

  componentDidUpdate(prevProps, prevState, prevContext) {
    const el = this.contentForRender();
    console.log('el', el);
    console.log('el_inner', el.innerHTML);
    // do something with el.innerHTML
  }

When i log it out, the 'el' variable in componentDidUpdate is typeOf: Symbol(react.element) and el.innerHTML is undefined.

Is there a different way of getting innerHTML for a React element?

I've tried using refs, but as I'm still reasonably new to React I'm not sure I've been doing it correctly and cant think of why it isn't working. Any help will be really appreciated!

Thomas Allen
  • 725
  • 5
  • 17
  • 30

2 Answers2

6

ReactJS doesn't expose the raw browser DOM, instead it has its own DOM interfaces.

The ReactJS equivalent of the HTMLElement interface does not have an innerHTML property for performance and safety reasons (because you shouldn't use it!).

Getting innerHTML (or rather outerHTML):

If you want a HTML string representation of a ReactJS DOM object, then you need to use renderToString. Note this will actually generate an equivalent of outerHTML, not innerHTML:

import { renderToString } from 'react-dom/server'

componentDidUpdate(prevProps, prevState, prevContext) {
    const el = this.contentForRender();
    console.log('el', el);
    console.log('el_inner', renderToString( el ) );
}

Setting innerHTML:

https://reactjs.org/docs/dom-elements.html

dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it’s dangerous.

Dai
  • 141,631
  • 28
  • 261
  • 374
1

Refs provide a way to access DOM nodes or React elements created in the render method.

In your case, you should add ref prop to your content and refer to it in componentDidUpdate:

constructor(props) {
  super(props);
  this.contentRef = React.createRef();
}

componentDidUpdate(prevProps, prevState, prevContext) {
  const el = this.contentRef.current;
  console.log('el', el);
  console.log('el_inner', el.innerHTML);
  // do something with el.innerHTML
}

render() {
  return <div ref={this.contentRef}><span>Lorem Ipsum</span></div>;
}
  • This won't work in a unit-test or server-side rendering scenario, btw. – Dai Mar 25 '20 at 09:52
  • @Dai it's an official way to access DOM elements in React. What do you mean by saying "This won't work in a unit-test"? If you have a browser-like test environment and the full ROM rendering it will work. In case of using just Node.js with a shallow rendering, you won't be able to access a DOM node because there's no DOM in that case. I can't argue about the server-side rendering. Haven't used refs in that case. – Oleksandr Kovpashko Mar 26 '20 at 10:12