Calling setState() behind an async call in ReactJS

I have blogged about how dangerous it is to use setState() during component lifecycle methods or render() functions. This is because the component can end up in an endless nested deep render. Dan Abromovic and the creators of ReactJS have also talked a lot about this subject. This is why we associate setState() with an event, like a button click.

A similar design pattern exists in ReactJS when we try to use setState() after calling an async function. In Redux we would not have this problem of course. However let's say you are rendering a location pin inside Google Map without the complexities of Redux state management. So all we want is:

  1. Geocode an address by calling Google Maps API
  2. Wait for the API response
  3. Set the map marker state so you get the pin at the right location

If step (3), the setState() function, is called before we get the API response, ReactJS is most definitely going to throw an error? Why? Because calling setState() before the component has fully mounted, or is still rendering, or is re-rendering, is a cardinal sin in ReactJS. 

So to make sure that step (3) is always called at the very end, we can easily make use of the async functions. Note that in setState(), the common pattern to call it synchronously, is to bind it to a function. Checkout this working code below to understand what I am saying:

Chaining API requests with Redux Thunk

Recently I wanted to be able to gather an array of objects on the first API request, and then for each object, fire off another API request that will get the object data using each object id. As you can imagine, the challenge is chaining multiple API requests using Redux Thunk and Axios in an asynchronous fashion.

Although the problem seemed simple, I realised that the solution is not equally trivial. I also figured out why this kind of design pattern is not documented:

Scenario 1:
Most users don't approach this kind of problem in this manner. In fact, most users just stop at the first API request to render a list of objects. Then they wait for the user to click on one of the objects to render the subsequent object details.

Scenario 2:
Users use other technologies other than Redux Thunk... technologies such as Redux Saga, to chain multiple API requests. In fact, this is one particular use case for which Redux Saga was designed.

Nonetheless, I was convinced that Redux Thunk can be still used. Apart from that, I was in a tight timeline to deliver a project so learning a new technology was out of question. The use case was for a  new aggregator system (from Reddit) that first fires an API to get latest Reddit posts, and then fires another API request for each Reddit postID to get the comments on each post:

I was able to solve this in redux-thunk by making two actions; one to fetch all, and one to fetch each individually. And, to chain them together, we treat each action as a promise (they return axios promises), then let Redux Thunk do its magic.

Let me show you the code snippet:

Notice that I made use of the getState() method to get the array of objects from the first API request promise. The getState() method provides us with a very easy way to pass state values (in this case, the array of objects) to action creators. It is important to understand that we are dealing with promises here, so the getState() method is exactly what we need - once the promise is fulfilled, the second action creator (and therefore, API request) is kicked off.

This design pattern is extremely important and will give you more mileage in your React Redux projects. For posterity, this is how you can then render the data inside your component:

Fire Action Creator after React State changes

I have recently come across a situation where I needed to wait for an axios async request to complete, get the final status from the response (either a success or an error message) and then, depending on the outcome, fire off an action creator. Additionally, I needed to complete the UX journey by redirecting the user to his dashboard through React Router.

In other words, what if we want to trigger an action creator in ReactJS after the Redux application state has finished all its mutations?

Since ReactJS is based on component re-rendering, this should be an easy task right? Well...not really...Usually this is the best task for UI rendering only...but conditional action triggering is something more advanced. Most experienced developers would suggest to use an aptly lifecycle Component method, such as ComponentDidUpdate(). This works in most cases, and in general, is the most recommend method:

The problem is that these lifecycle methods, and any other methods outside the render() function, such as generic helper methods, do not work well with React Router 4, specifically <Redirect /> *. So for example, in my case, I wanted a customer to pay for a subscription, then when my backend server sends a specially crafted response, this will be updated in my Redux state, and hopefully, trigger this action creator. After that, I want the customer to be redirected to a Dashboard component.

*Although we could not use the <Redirect /> method, we can use another React Router 4 redirect technique which works well with helper methods outside render() functions. This technique will be described in a future post. As a sneak peek, this entails using the this.props.history() technique.


So if I cannot listen to state changes inside a lifecycle/helper method, what is the alternative? We can always listen to state changes inside the rendered component itself. One trick I like to use is putting a ternary operation or a classic old if condition that triggers when on a state change. Remember, when the state is updated, the component is always re-rendered through React Redux until the condition is matched, and triggering the next action creator. This is the flow I am using:

Note that in my particular case,  the success or error object is only made available inside the state tree once the axios operation is complete, hence why I am using the !! notation.

Remember that once the action creator is fired, remember to reset the state tree, otherwise you will end up an infinite loop and keep triggering the same action creator :)

Updated and Better Solution

There is actually a better way of doing the redirect and still using the recommended React component lifecycle methods. Since the <Redirect /> technique does not work well with these methods, I suggest to instead use this.props.history.push() inside the ComponentDidUpdate() to perform a redirect. Just remember to wrap your component with the withRouter() HOC. The code will therefore look similar to this:

How to pass ReactJS state into Redux Action Creator

Although there are differing opinions on whether accessing state in action creators is a good idea (for example, Dan Abramov strongly discourages such practice), there are some edge cases (such as checking for cached data or for authentication related situations), which will make passing the Redux state into an action creator quite a useful concept.

It turns out that Redux makes this quite easy, through the getState() function. Quoting the official Redux documentation:

getState() returns the current state tree of your application. It is equal to the last value returned by the store's reducer

So let's say we have a reducer that returns the state of a Redux Form and of the application's authentication such as the following:

For the action creator to access the auth state, all we need to do is use the getState() function. First we need to pass it as the second argument after the dispatch, and then save its return as the application state tree:

To get a specific value instead of the whole tree, since state is an object, I can use the object dot notation, as in the quoted example. Alternatively, you can use the ES6 destructuring notation: const { auth } = getState()

In general I try not to pass any state to the action creator and try to solve my problem in a different way (for example, by dispatching multiple actions). But if there are still no alternatives, at the very minimum, I recommend passing the state at the very end of the application state chain. This is to minimise the risk of application state mutation in the wrong places.

Update React State from Component Props

ReactJS state and prop data model is so flexible that I cannot fathom how to solve information system problems otherwise, and I keep reminding this to myself everyday I use it. Recently I came across a situation where I needed to re-use a component, passing it props from a parent component, and having the component (or global) state updated on-the-fly.

Let me briefly describe the situation I am referring to. Let's say I am using the official Stripe Checkout component to for my next SaaS application. I want to have a re-usable component so I can create a multi-tier pricing subscription plan.

The Stripe Checkout component will therefore look like this:

Notice that this Stripe component can be used by a parent component so I can generate 3 different pricing plans. This is simply achieved by calling this component three times and using the appropriate props as follows:
Now if I want to be able to set the application state for the planPrice, so other components are aware that what the chosen price is, can be simply achieved by binding an onClick function call to the Button component inside the Stripe Checkout component:

This is a very nifty trick that most ReactJS developers should be aware of. This allows us to re-use our components without losing control of the component state.

Material UI 1.0 with Styled Components

Material UI 1.0 brings with it huge styling flexibility compared to its predecessor. For starters, now you can easily theme and style the components by passing props like this:

This simple requirement used to be a big pain in the previous version of Material UI. Not only that, but it is also much easier nowadays to combine Material UI with Styled Components.

Let's demonstrate how easy it is to style an AppBar.

In this example we are basically styling the default Material UI AppBar component by doing a styled Button and a styled Typography component. Additionally, I am giving a nice blue color to the AppBar by passing the color prop. The resulting AppBar will look like this:

About my coding environment

People often ask me about my environment setup, specifically the IDE and the themes that I use.

I currently use VS Code, which I prefer over other IDE's that I have used in the past (including vim, Sublime, Atom and IDEA). The reasons are predominantly due to its large community base and being very lightweight, fast and extremely hackable.

I use the Oceanic Next Italic (White) theme as it provides a pleasant dark interface that allows me to code for long hours without straining my eyes. This theme also exposes italic elements that can be leveraged using specially engineered fonts. Since I don't afford to spend $600 on a font like Operator Mono, I have built my own custom font using FontForge, based on Fira Code and Script12-BT.

The result of my setup looks something like the below:

Choose an SSH key to push to your Git repository

Usually Git assumes that you are using your default SSH key if you want to push to a secure Git repo. However this is not always the case and you might want to choose specific keys for specific repos. How can you do it? Simply through the following environmental variable: