2
votes

Can you, using React, create router Links (or other components) from data returned from ajax-calls? NOT using the render function.

Background: We have a large 3rd party non-react javascript library that dynamically renders HTML from an AJAX call. We control the input (i.e. the ajax-response), but not the output. I want to input links (a href) and get them rendered as React Router Links. To wrap the non-react component I have created a component which basically have two parts: componentDidMount where I initiate the components and render where I output a div (for the 3rd party javascript library). Ideally we would like to inject reactJS component directly from the ajax-response:

[{'textToRender': '<Link to="/home" title="home">home</Link>'}]

Unfortunately this would only render the text:

<Link to="/home" title="home">home</Link>

Any idea if this is possible?

UPDATE: The non-react component is somewhat complex but for the sake of this question let us say it takes one ajax-url parameter and renders output to that div. The nonreact component expects HTML input from the AJAX, but I have the ability to execute javascript before injecting the HTML into that component.

I.e. the non-react component fetches data from the AJAX call and update its div.

So the init looks like this:

componentDidMount() {
  $('#nonreact').NonReact({ 'ajax': 'http://someurl..', 'transform' : function(data) { //here I can run some JS-code prior to nonrect render; return data; } });
}

And my component render looks like this:

render() {
  return (
   <div id="nonreact"></div>
  )
}
3
How does the 3rd party code relate to your current code? Can you provide a more complete example of what you are doing now?Juho Vepsäläinen
I have updated the question with some code.mathan
Is it possible for you to return the markup in an intermediate format (JSON)? If so, you could write a transformation from that format to React quite easily. This is where hyperscript could come in handy.Juho Vepsäläinen
Yes. I prior to the component render I have the chance to run some transformation. Basically I can pass in a function(data) { //do whatever; return data; } Are you saying I can create my react component here?mathan
Exactly. I'll write you a little example in pseudocode to give you a better idea.Juho Vepsäläinen

3 Answers

2
votes

You could do something like this:

componentDidMount() {
    $('#nonreact').NonReact({
        ajax: 'http://someurl..',
        transform: (data) => {
            // 1. transform data to some intermediate format
            // {to: '/home', title: 'home', text: 'home'}
            const {text, ...props} = transform(data);

            // 2. create React element and set it to `link` state
            this.setState({
                link: React.createElement(Link, props, text);
            });
        }
    });
}
render() {
    // 3. Use {this.state.link} here
    ...
}
1
votes

In React, <Link to="/home" title="home">home</Link> is just the sugar for

React.createElement(
  Link,
  { to: "/home", title: "home" },
  "home"
);

It does is transformed into that before your code is executed. Simply placing the text <Link to="/home" title="home">home</Link> won't do anything special.

You will probably make your life easier if the response is more like

[{'textToRender': {to: "/home" title: "home" text: "home }}]

Then, in a component that actually renders these you would iterate over these and create Links for that, in render

render: function() {
  var linksResponse = ... // how ever you get them
  var elements = linkResponses.map(function(entry) {
    return Object.keys(entry).map(function(text) {
      var linkData = entry[text];

      // real action happens here
      var link = <Link to={linkData.to} title={linkData.title}>{linkData.text}</Link>;
      return link;
    });
  });
  return elements;
}
1
votes

It's absolutely possible. At my current project I fetch a large chunk of markup from an API. This is normal HTML with a few custom tags in it. These custom tags have corresponding React components in my app. What you want to to is make us of a library such as html-to-react (https://github.com/mikenikles/html-to-react). The way this works is that it parses the markup string and creates an object that represents the DOM for that markup. This object is in turn rendered to a React element. You can have custom tag handlers, telling html-to-react what to do when it finds a non-standard tag in the markup.

It works something like this:

let markupstring = '<div>lots of markup, 100kb</div>' // String
let parsedMarkup = htmlparser.parseWithInstructions(markupstring, function(){return true;}, processingInstructions);

How to configure prosessingInstructions is documented in html-to-react documentation. parsedMarkup is a valid React element.