Consuming Chuck Norris API from ReactJS

Experimenting with incremental software development practices with ReactJS

Marco Garofalo
10 min readJun 1, 2021

There is an infinite amount of resources out there for ReactJS to learn from, but it becomes quite challenging to find quality content which does actually help us growing in the right direction.

One of the things I don’t see very often is how to apply incremental software development practices in a real codebase, so I wanted to take this opportunity to experiment a little bit with ReactJS and Test Driven Development by consuming a remote RESTful API.

I wanted to use a publicly available API for this project, and while exploring the web, my attention was caught by api.chucknorris.io. Yeah that’s right, someone has published a RESTful API that returns jokes about the legendary Chuck Norris.

I believed it had the perfect balance between simplicity and fun, so let’s give it a try!

Let’s set the scene

Your team and the client are having a great time, you all share a profound respect towards the legendary Chuck Norris and you agree it’s time to make the world a better place.

We want to ensure every fan in this world can go into a web page and get amused and reminded about our legendary friend, but how do we proceed?

After a great pairing session with our Product Manager, we decided to start really small, and we come up with a couple of user stories, making sure they are small enough and have all that is necessary for a good story (i.e. INVEST principles).

  1. As a #1 fan of Chuck Norris, Steve wants to see a joke about his favourite celebrity, so that he can feel amused by Chuck Norris legendary reputation
  2. As a #1 fan of Chuck Norris, Steve wants to see different jokes about his favourite celebrity, so that he can continue to feel amused by Chuck Norris legendary reputation

These two stories are enough to start with, and we can certainly add more stories down the line, for instance looking after on demand capabilities and unhappy paths.

Before we start building anything we need to add some acceptance criteria to our stories, so that we have a rough understanding of what is acceptable for Steve.

Now here is where the N (Negotiable) and the T (Testable) part of the INVEST principles come very handy, especially to help us narrow down what we want to achieve and know when we’re done.

We paired with our Product Manager and we agreed with the following acceptance criteria for the first story.

Given Steve visits the home page
When the page has finished loading
Then Steve should be presented with the following joke
“Chuck Norris doesn’t read books. He stares them down until he gets the information he wants.”

We negotiated the story so to cover only the very first happy path, where we do show only one carefully selected joke about our legend, this will allow us to start small and focus on getting things done.

Ok we now have enough information to start building something for Steve.

First user story

First thing first, as you can imagine from the title of this article, we are going to be using ReactJS, together with TypeScript, to build our app.

We also mentioned that we are going to integrate with a third-party public API offered by api.chucknorris.io, so we don’t need to invest any time building a dedicated backend for this purpose.

That being said I hope that at this point you already figure out that we don’t actually need to build any integration yet for the first story, yeah that’s right, we can simply hardcode the very first joke and fast track directly into the second story, where we are going to have some action!

Great, let’s start by creating a new react application using the create-react-app command line tool.

create a new react app

Let’s get rid of everything in the App component until we are left just with this.

App component stripped with the essential

What’s the plan? Ideally we want to take a look at the functional part first, then we will take care of styling, and once we are done with that we can move onto the second story.

So we talk to our Product Designer and we agreed on having some sort of dialog or speech bubble, think Gameboy-like, which is going to display the joke with a typewriter effect.

This gives us a rough idea on how things will be laid out on screen, we can then start by creating a new component, namely ChuckNorrisDialog and prepare a test for it as well.

ChuckNorrisDialog empty test
ChuckNorrisDialog empty implementation

Our job here is quite simple, we just want to make sure that, once the component is mounted, we display the given joke on the screen, so we can write a simple failing test (remember we are practicing TDD), which is going to look like this:

ChuckNorrisDialog test for rendering the hardcoded joke

How do we make it pass? Well as mentioned earlier this story just is simple enough for us to go through a very first setup, so let’s make the simplest possible implementation for it and move on.

ChuckNorrisDialog implementation with the hardcoded joke

We have enough functionally to help us satisfying our first story, we just have to load this component in the App and work a little bit on the styling.

ChuckNorrisDialog plugged into the App component

Let’s do start the development server to see how it looks like

Start the development server via yarn
First look for the app

Ok, it works as expected but it looks sadly empty.

Jokes with style

We got some serious ideas from our Product Designer, let’s go do some CSS magic and give it a little revamp. (I am going to provide the CSS code as part of the source code linked to at the end of this article).

We are going to rename App.css into App.module.css to hold our basic styling, and then add a ChuckNorrisDialog.module.css as well. If you are not familiar with CSS modules in React you can read about them here.

We are also going to install a new font, namely the pokemon-font, available here, and import its css directly into our App component.

In order to install pokemon-font we can simply run yarn add pokemon-font .

And for the final touch we decided to add an avatar on the page, I found this one that looks pretty good, and we can simply put it within an asset folder and load it directly in the code like this:

App component uses CSS modules
ChuckNorrisDialog uses CSS modules

And voila, much better!

New look for the app

I believe we are done with the first story, let’s commit the changes and move to the second one.

Second user story

We haven’t defined any acceptance criteria for the second story yet, so let’s do that first.

Given Steve visits the home page
And there is already a joke displayed
When Steve refreshes the page
And the page has finished loading
Then Steve should be presented with a different joke every time

Now, we can argue that we can actually implement this story in many ways, we could for instance have a static file locally populated with loads of jokes taken from the internet, but the main aim of this exercise is to consume a real RESTful API so that’s what we are going to do.

The Chuck Norris API supports a very simple operation that return a random joke, and the structure of the request and response seems pretty straightforward.

Here’s a sample request:

Chuck Norris API request structure

And this is the payload in the response:

Chuck Norris API response structure

What’s the plan here? Ideally our ChuckNorrisDialog component will leverage some other Client component, which in turn will be responsible for the API integration. Then we are going to use the context hook in combination with a context provider in order to supply the client to any part of the app. If you are not familiar with React context you can read about them here.

Let’s start by creating a simple interface for the API, a basic client test and implementation.

ChuckNorrisApiClient empty test
ChuckNorrisApi and ChuckNorrisApiClient empty implementation

I read many articles and seen people testing this type of component by employing conventional mocking techniques, leveraging the fetch API from one side and then use a fetch polyfill or stub in the test.

Although this might work, the aim of a test is to give us confidence that the code works as expected, so the closer we get to replicate the production runtime the more confidence we gain.

Luckily for us there is a better approach, we can leverage the Mock Service Worker, which can intercept real http requests and provide a way to prepare canned responses declaratively.

Let’s add it via yarn and prepare our first failing test.

Add mock service worker via yarn
ChuckNorrisApiClient tests for the happy path to consume the random joke API

In order to make it pass we can simply use fetch and cast the response as a Joke.

ChuckNorrisApiClient implementation for the happy path to consume the random joke API

Cool, we now have a functional and simple API client implementation.

The next step would be to implement a simple context provider that we can use in order to inject the client wherever we need it.

ChuckNorrisApiProvider and context to inject the client

What’s next? It’s time to implement the changes into our ChuckNorrisDialog component, by writing more tests first, obviously!

In order to get extra support for writing our test cases, we will make use of an additional jest extension, particularly helpful when mocking interfaces.

We can add then by running

Add jest-mock-extended via yarn

Here’s our updated test:

ChuckNorrisDialog tests for using the ChuckNorrisApi to then display the joke

Because we are introducing asynchronous side-effects, using the useEffect hook and promises, our tests needed a little bit of extra attention with respect to rendering, failing to do so increases the risk of bringing up the (in)famous error:

(in)famous act error

We can avoid that by making sure operations that lead to rendering are wrapped against, what I call, a fully fledged act . That looks like this:

Fully fledged act

The important bit of this fully fledged act is the callback, because it’s async, and apparently that ensures all the pending promises are resolved before continuing. If you want to know more, here is a better explanation of how act works.

Here the updated implementation for the ChuckNorrisDialog

ChuckNorrisDialog implementation for using the ChuckNorrisApi to then display the joke

Great we just have to go inside our index.tsx and make sure it’s setup correctly, once this is updated we can commit our changes and we should be done with this story as well.

Create the ChuckNorrisApiClient and injects it into the ChuckNorrisApiProvider

Whenever we refresh the page we get a new joke, which is exactly what we wanted!

Different jokes displayed to the user

What’s next?

When working incrementally, we have the ability to work on different dimensions, and decide what we want to expand on.

For instance we started by looking at how to provide just one single joke, hardcoded, then we moved into presenting multiple different jokes.

But there are other things we might want to consider next:

We could think about adding on-demand capabilities, i.e. improving user experience by providing Steve a “Next” button to get another joke instead of relying on a page refresh.

Example for on-demand button to navigate through the jokes

Maybe think about unhappy paths, i.e. what happens if, for some reason, the Chuck Norris API temporarily stops to respond, should we present something else to Steve? Should Steve be able to retry later?

Example for displaying errors, including a retry button

What about narrowing down the random jokes within specific categories, supported by Chuck Norris API? The possibilities are endless.

Conclusion

We just scratched the surface here, but I hope you enjoyed our little adventure.

The source code used for this article is available here (bonus: this code actually has few more commits which covers the on-demand and error handling stories).

I’ll see you at the next one!

--

--

Marco Garofalo

Enthusiast software engineer and XP practitioner, supporter of Lean and User Centred Design. Advocates for delivering user and business value early and often.