Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render a string with JSX in React

I need to render an HTML (JSX) string in a React class. I don't know if this is possible or not. dangerouslySetInnerHTML is not valid for me because I have different react components inside this file. It's not plain HTML.

I have an example with the expected result: https://jsfiddle.net/86rg50re/1/

var MyComponent = React.createClass({
    propTypes: {
        owner: React.PropTypes.string
    },

    render: function() {
        return <div>Congrats {this.props.owner}! you have rendered MyComponent ({this.props.children})</div>;
    }
});

var Hello = React.createClass({
    render: function() {
        return <div>Header <MyComponent owner={"Daniel"}>Yayyyyyy!</MyComponent></div>;
    }
});

But what I have is this:

var Hello = React.createClass({
    render: function() {
        var content = '<div>Header <MyComponent owner={"Daniel"}>Yayyyyyy!</MyComponent></div>';
        return transformStringToJSX(content);
    }

Obviously transformStringToJSX doesn't exists.

Is there a way to render jsx strings?

like image 835
gyss Avatar asked Oct 21 '15 14:10

gyss


People also ask

How do I render a string in React?

To render the html string in react, we can use the dangerouslySetInnerHTML attribute which is a react version of dom innerHTML property. The term dangerously is used here to notify you that it will be vulnerable to cross-site scripting attacks (XSS).

How do I convert a string to JSX?

There're several ways to convert HTML Strings to JSX with React. One way is to put the string in between curly braces in our component. Another way is to put the string in an array with other strings or JSX code. Finally, we can use the dangerouslySetInnerHTML prop render an HTML string as HTML in our component.

Can we use JSX in React?

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript. JSX produces React “elements”.

What is ${} in JSX?

You use ${} in string templates like const k = `my name is ${name}` you use {} whenever you want to put some Java code in your JSX code like <div attr={name}>{name}</div>


2 Answers

You can use babel to transform it

npm install --save babel-core

Then in your code

var babel = require('babel-core');
var Component = eval(babel.transform('<div><MyComponent /></div>').code);

Please note that it is generally a bad idea to convert strings to executable code.

like image 133
hampusohlsson Avatar answered Sep 22 '22 16:09

hampusohlsson


The most upvoted answer simply does not work, skips various crucial steps, and doesn't explain where the code should go. I'm not sure if the poster just didn't actually run the code or what. Anyways, to actually get it working you need to do something like this:

npm install @babel/core

npm install @babel/preset-react

You need to use babel to transform the JSX into valid javascript that can run clientside on the server side. The serverside code in next.js

export async function getServerSideProps() {
    const stringToRender = require('@babel/core').transform('<h1><Component/></h1>', {presets: ['@babel/preset-react']});
    return {
        props: {
            stringToRender
        }
    }
}

Now we need to evaluate the string on the client:

import React from 'react';
import Component from '../component'; // Import your component

export default function Page({stringToRender}) {
    const [content, setContent] = useState(null);
    
    useEffect(()=>{
        // It is necessary to evaluate within useEffect and window so that React are available.
        window.Component = Component; // This makes Component defined in the `eval` call.
        setContent(eval(stringToRender))
    }, [])
    
    return (
        <div>
            {content}
        </div>
    )
}

export async function getServerSideProps() {
    const stringToRender = require('@babel/core').transform('<h1><Component/></h1>', {presets: ['@babel/preset-react']});
    return {
        props: {
            stringToRender
        }
    }
}

This code will actually run to the desired effect. If you have any additional components to render you will need to set them individually on the window object so that the components will be defined when the eval() call is made.

like image 43
ICW Avatar answered Sep 24 '22 16:09

ICW