Making RESTful API call from React.js Making RESTful API call from React.js reactjs reactjs

Making RESTful API call from React.js


Fetching inside of component using componentWillMount is not a right place, in case when you need to render server side. You need to somehow move it out form component, and pass actual data as props after it is fetched - for example as @JakeSendar suggested in his answer.

I have some experience doing isomorphic app with React, and the main problem I faced is how to wait until all data would be loaded before first render

As @FakeRainBrigand already mentioned in comments, there is not only one way to do this, and it depends from your requirements.

There is few ways to do build an isomorphic app, the some interesting from my perspective is: https://github.com/webpack/react-starter and http://fluxible.io/

But, the most elegant way to do this, as I figured out for myself - is to organise asynchronous rendering for react components, in particular using RxJS.

In general my application is structured as following:

  1. views - React components without any logic (just a view)
  2. models - Observables with current state (initial data is loaded using superagent, then combined with other models and/or actions results).In simple case it is something like:

    Rx.Observable.defer(fetchData).concat(updatesSubject).shareReplay()

  3. actions(or intents) - Observers used to collects user input, do something, and dispatch action results to subscribers models and/or other actions. In simple case something like:

    updatesSubject = new Rx.Subject();

    action = new Rx.Subject();action.switchMap(asyncRequest).subscribe(updatesSubject)

  4. components - Observables(stream of virtual DOM elements) combined from models, other components and actions (I have a note about this, explaining how and why to create Observable React elements with RxJS), also now I am planning to add partial components (tuple from: react component, observables, observers, and properties. partially filled with using DI)

  5. router - component responsible to handling location changes, in general main feature is to map location changes to stream of virtual DOM elements and meta information. But in details, it is bit more complicated in my case(url generation, active url highlighting, handling scrolls when navigating, also it has possibility of nested routes and multiple views)

All this is assembled together using DI container, in my case similar to angular2 DI container, but a lot simplified for my specific needs.

Components, models and actions are created using DI.

On server side application is like this:

var rootInjector = new Injector();// setup server specific providersrootInjector.provide(..., ...)app.get('/*', function(req,res){    var injector = rootInjector.createChild();    // setup request specific providers    injector.provide(..., ...);    injector.get(Router)       .first()       .subscribe(function(routingResult){           res.render('app', {              title: routingResult.title,              content: React.renderToString(routingResult.content)          });       });}

and similar on client side:

var rootInjector = new Injector();// setup server specific providers// actually this is omitted in my case because default providers are client siderootInjector.provide(..., ...)contentElement = document.getElementById('#content');rootInjector.get(Router)   .subscribe(function(routingResult){       document.title = routingResult.title;      React.render(routingResult.content, contentElement)   });

In comparison to flux, it is more declarative and more powerful way to organise app. And in case of isomorphic app - for me, it looks much better that various hacks with flux. But of course there is drawbacks... - it is more complicated.

Likely later, I will opensource all this, but for now - it is not quite ready to be published.

UPD1:

Original answer is a bit outdated(later I plan to update it), and I have some progress in this area.

Links to code mentioned above, already opensourced:

  • DI container: di1
  • Container for react componentns(connecting view to observables and obsrvers): rx-react-container
  • Starter template, for implementing isomorphic widgets, using RxJS and React, and libraries above: Reactive Widgets

About complete application(work still in progress, and documentation there is not quite good, but in general it should be clear):

  • Router built especially for isomophic reactive applications router1 and react components to use it router1-react
  • Application template with router and all libraries mentioned above: router1-app-template


React's renderToString method (for rendering components on the server) is synchronous. Therefore, any sort of async task, such as your api request, will still be pending by the time the component has rendered.

There are a couple of ways you can go about fixing this, depending on whether or not you want to fetch your data on the server or client.

If you choose to fetch the data on the server, first move your api-request logic outside of your component. Then, render your component in the callback, passing the fetched-data as a prop. It would look something like this:

response.on("end", function (err) {  var data = JSON.parse(buffer);  var markup = React.renderToString(Component({categories: data}));});

Inside your component, you'd be able to access the data via this.props.categories.

The other option is to handle the api request on the client. You would make an AJAX request in componentDidMount, and set the component's state from the fetched data. It would look very similar to what you have now, the key difference being that your request logic would live in componentDidMount (async, called on the client) rather than componentWillMount (not async, called on the server).


You should use superagent, works really good for me, also you are missing the most important part, you should use flux to fetch data from a server, flux is the way that facebook strongly recommended, it's pretty easy to use flux architecture.