0

I got the following to show on my page:

export class OverworldComponent extends React.Component<OverworldComponentProps, {}> {
    render() {
        return <b>Hello, world!</b>
    }
}

Instead of Hello, world! though, I would like to output a clone of an HTMLElement already on the page. (A table, to be specific.)

export class OverworldComponent extends React.Component<OverworldComponentProps, {}> {
    render() {
        return document.querySelector('div.file div.data table').cloneNode(false);
    }
}

This compiles but causes the following error (Chrome Inspector):

enter image description here

And it doesn't feel right to just look for ways to "cast" my HTMLTableElement to something React-compatible. When I did try to cast with <HTMLElement>, it was interpreting it as a tag (missing closing tag) instead of casting. So I must not understand what the mechanics is within render(). I think there's something in the framework I should be doing differently, but I don't know what.

For context, I'm in the middle of a hackathon that ends tomorrow, and I began learning React and Typescript today, so I'm missing a lot of knowledge (and lack any experience at all).

Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145
  • So it makes sense why it's not rendering, maybe you can clone it with react's 'cloneElement' function. `return React.cloneElement(querySelector('div.file div.data table');` or maybe createElement is more valid here.. – Sterling Archer Mar 16 '18 at 01:24
  • why clone? react can't render a virtual dom this way.... – Daniel A. White Mar 16 '18 at 01:24

1 Answers1

1

document.querySelector('div.file div.data table').cloneNode(false); is pure Web API. This means it returned DOM node, not React Component.

The child of React Component must be also a React Component.

If you want to inject a DOM node into a React Component, consider using dangerouslySetInnerHTML https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

For detail:

dangerouslySetInnerHTML is a prop and its value is an object:

{ __html: '<p>a chunk of html source code</p>' }

In your case, it could be:

{ __html: document.querySelector('div.file div.data table').innerHtml }

or

{ __html: document.querySelector('div.file div.data table').textContent }

You also could use nodeValue, innerText

Read here to see the differences and pick the best one: nodeValue vs innerHTML and textContent. How to choose?

Khoa
  • 2,632
  • 18
  • 13
  • 1
    Thank you, this worked! I did do some research on XSS attacks via `dangerouslySetInnerHTML`, and found [a great example](https://stackoverflow.com/questions/44593485/example-of-bad-react-dangerouslysetinnerhtml) of a simple exploit. Indeed, I think I need to find a safer solution for public release. But for now it's fine because it's for an internal site (company's GitHub Enterprise) and I know it's probably impossible for an injection like the previously linked example because I'm cloning an HTML table has escaped everything for a `
    ` view.
    – Andrew Cheong Mar 16 '18 at 05:56