425nesp
425nesp

Reputation: 7593

How do you render div objects from non-React libraries in React?

I found a library I want to use in my project, but it's a plain JavaScript library and doesn't know anything about React.

https://www.npmjs.com/package/json-formatter-js

Is it possible to use this in my React project? I tried this, but the render crashes.

class JSONView extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        const formatter = new JSONFormatter(this.props.data);
        const Rendered = formatter.render();

        return (
            <div>
                <Rendered />
            </div>
        );
    }
}

The error I get is this.

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

The typeof Rendered is object.

Upvotes: 0

Views: 74

Answers (3)

Balagoni Harish
Balagoni Harish

Reputation: 106

Try this

class JSONView extends React.Component<any, any> {
    constructor(props) {
        super(props);
    }

    public refs:{
        JsonDiv: HTMLDivElement;
    };

    componentDidMount(){
        const formatter = new JSONFormatter(this.props.data);
        this.refs.JsonDiv.appendChild(formatter.render());
    }

    render() {
        return (
            <div ref='JsonDiv'>
            </div>
        );
    }
}

or this one

class JSONView extends React.Component<any, any> {
    constructor(props) {
        super(props);
    }

    render() {
        const formatter = new JSONFormatter(this.props.data);
        return (
            <div dangerouslySetInnerHTML={formatter.render()}>
            </div>
        );
    }
}

Upvotes: 1

Nithin Thampi
Nithin Thampi

Reputation: 3689

Looks like the library returns HTMLDOMElement from function formatter.render().

So you can't use JSX syntax to render it.

While I agree that the other answers can work, I would prefer using a dom ref and appending the returned HTMLDOMElement from formatter.render() in componentDidMount lifecycle method.

import React, { Component } from 'react';
import { render } from 'react-dom';
import JSONFormatter from "json-formatter-js";
import Hello from './Hello';
import './style.css';

class JSONView extends Component {
    constructor(props) {
        super(props);
    }

    ref = null;

    componentDidMount(){
      const formatter = new JSONFormatter(this.props.data);
      const Rendered = formatter.render();
      this.ref.appendChild(Rendered);
    }

    render() {     
        return (
            <div ref={e => this.ref = e}>
            </div>
        );
    }
}

render(<JSONView data={{Hello: {Hello:  "World"}}} />, document.getElementById('root'));

Working Demo You can drill down to the object.

In the other approach which makes use of dangerouslySetInnerHTML or just rendering the string content, you have the risk of losing DOM events.

import React, { Component } from 'react';
import { render } from 'react-dom';
import JSONFormatter from "json-formatter-js";
import Hello from './Hello';

class JSONView extends Component {
    constructor(props) {
        super(props);
    }

    ref = null;

    render() {     
        const formatter = new JSONFormatter(this.props.data);
          console.log(formatter);
          const Rendered = formatter.render();
          console.log(Rendered.innerHTML);

          return (
            <div>
                <div dangerouslySetInnerHTML={{__html:Rendered.innerHTML}} />
            </div>
          );
    }
}

render(<JSONView data={{Hello: {Hello:  "World"}}} />, document.getElementById('root'));

Working Link You cannot drill down to the object.

Upvotes: 0

Excalibur
Excalibur

Reputation: 367

edit

try

{ Rendered }

there might be warning if it ships class with html tags.

between curly braces {} and it'll work (99 %) and if it doesn't then continue reading.


you can render if it returns string.

currently it might b returning html object which is incompatible with react dom render.

if it contains class property then it'll cause problem even if it's in string format.

you can use react-html-parser to render html strings in react. reference

const Rendered = formatter.render().outerHTML   // this will give you html string instead of html object

now use react-html-parser if you don't wanna manage class attribute name conflict as react accepts className

import ReactHtmlParser from 'react-html-parser';


class JSONView extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        const formatter = new JSONFormatter(this.props.data);
        const Rendered = formatter.render().outerHTML;

        return (
            <div>
               { ReactHtmlParser(Rendered) }
            </div>
        );
    }
}

Upvotes: 0

Related Questions