简体   繁体   中英

ReactJS: Create components, not using render for non-react libraries

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 (ie 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.

Ie 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>
  )
}

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;
}

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.

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
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM