-3

Alexnm Shows the terribly disgusting architecture you must provide to simply have a server wait before an API call is complete before a server responds to a client.

He shows that you must first document each component of your entire app in a single, non-hierarchical flat list, then filter through every single component to see if a component has a API "data-requirement" for every single request, then store the output of that API request in a global redux object (also disgusting), then somehow pass that back to the object in the hopes it doesn't collide with other requests.

This is because ReactJS "lifecycle" hooks aren't actually lifecycle hooks at all, and is instead "fast and free" (and fun).

I don't really care for any of these libraries, ES[xyz] syntaxes, and strange philosophies, but what I would like to do is return the an http response after and API call is made, i.e.

render() {
    // do an API call.
    // return a response.
}

I've seen uses if fetch(xyz).then(() => {}) and so many other colorful brackets and functions where I'm not totally sure where parameters go in or where they go out, and I can't seem to figure out how to simply hold off the next line of code before the previous line of code is complete. In then(() => {}), which is syntaticly beautiful, I'm unable to return a value in any way at all. It's called a function, but I'm having difficulty achieving anything other than a side side-effect, and am unable to return a result of any kind.

Does anyone know how to make the render(), on it's own, wait for an API call?

Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111
  • 2
    This isn't a direct answer (hence the comment), but - you really, really don't want `render` to block on API calls! That's going to hang the page and generally make your application feel sluggish. The idea is that you call `setState` on your component within the `then` of your `fetch` (which runs after the HTTP request has completed) to re-render your component once the data has arrived. Then you can render a loading spinner/placeholders/some big bold text saying "*IT'S LOADING I SWEAR*" in the meantime. – Joe Clay Aug 01 '19 at 19:58
  • Relevant section of the docs, if you've not already stumbled across it: https://reactjs.org/docs/faq-ajax.html – Joe Clay Aug 01 '19 at 20:00
  • So for context, I'm doing server-side rendering (for SEO reasons). I've tried doing an API call in `componentDidMount` (and others) and setting state in there, but from logging, I've discovered `render` is called before `componentDidMount` is done. `render` reads the state, but the state isn't set yet. – Alexander Kleinhans Aug 01 '19 at 20:02
  • 3
    I'm not quite sure what the question is here, it reads to me like basically a rant, firstly about some technicalities of React (that I'm not too familiar with so can't really comment if they're fair or not), followed by a rant against Promises, it seems just because they're asynchronous? While I sympathise that asynchronous programming is quite hard, it's 1) unavoidable in JS unless you want to give users a truly horrible experience and 2) promises, once you get used to them, make it much easier than it ever was before. (`async/await`, which is still promise-based, makes it even easier) – Robin Zigmond Aug 01 '19 at 20:08
  • @Display name: Ah, I see - in that case, you probably don't want to be fetching the data within the lifecycle hooks (unless you want the request to run again on the client). Fetch the data *before* rendering the component (e.g. in your server's request handler), and pass it in to your component as props. [Next.js](https://nextjs.org/docs#fetching-data-and-component-lifecycle) is a nice pre-baked package for doing this (without the waters being muddied by Redux, etc) - hopefully it'll give you some inspiration. – Joe Clay Aug 01 '19 at 20:09
  • I try to understand your problem, but I can't. – Tolotra Raharison Aug 01 '19 at 20:33
  • Are the lifecycle methods even called during SSR? The only pre-rendering I've done with React has been with static rendering, so maybe it's different, but in that situation `componentDidMount` and the rest don't get called until the page is loaded in the browser. – Herohtar Aug 01 '19 at 20:53

1 Answers1

0

As for philosophies - you may want to read more on flux patterns - which were architectural design principles conjoured at Facebook. The efforts were to handle global state in a Single Page Application, or SPA.

Per your current syntax issue - you may utilize promises with arrow functions. Promises were introduced in ES6 as a solution for handling asynchronous requests cleaner.

Using your example fetch(xyz).then(() => {}) one may execute requests synchronously by:

render() {
   Promise.resolve(fetch(xyz))
   .then((response) => {
      // Do something with this response - for example..
      if (response.data) {
         axios.get("http://google.com")
         .then((response) => {

         console.log(response.data);

         })
         .catch((err) => {

         // Do something with this error
         console.log(err);
         })
      }
   })
})

return (
    <div>

    </div>
)
}

I won't get into time complexities - but the above solution will fire off the fetch(xyz) request, then once that requet has completed - we fire off the next request. This is called promise chaining - more information may be found here: https://javascript.info/promise-chaining

If your goal is to simply make a call and use the data once the component has rendered, or mounted, you may do something cleaner and react friendly (non blocking) like the example below:

import React, {Component} from 'react';

class Example extends Component {
constructor(props) {
    super(props);

    this.state = {
      data: ''
    };
}

componentDidMount() {
   Promise.resolve(fetch(xyc))
   .then((response.data) => {
       this.setState({
         data:response.data
    });
   })
};

render() {
  const data = this.state

  return (
    {data} 
  )
}