ReactT Dark_870x220

This is the second article of a two-part series. In the first article, we learned about advanced patterns in React like High Order Components and Render Props. We examined what exactly these patterns are, how we can use them to achieve a nice level of code reuse and state logic share throughout our projects, and also how they can help us to build better applications. In this part, we'll learn more about React Hooks, what are they and how we can replace some of these patterns to increase state logic reuse with React Hooks.

We know that composition in React is an important topic, and lately a lot of people have started to talk about it. It can have a huge impact on our applications if implemented the wrong way and with the wrong patterns, so we must strive for better component composition in our code. With it we can automatically improve our code readability, and we get less code with more state logic share throughout our applications.

The problem with some advanced patterns in React such as High Order Components or Render Props is that sometimes it’s overkill. Also in some cases it can leave our code heavier and too hard to understand for other developers. The fact that these patterns are advanced is another problem for some developers - they don’t know exactly how a Render Prop works and might get confused and lost with it.

But how we can replace these patterns in such cases with a more modern approach, making our code more concise, more readable, and with a nice level of component composition and code reuse? We can use React Hooks!

In the latest version of React, the React team released React Hooks. It’s a whole new way to deal with the state in our components, especially now that we can use and manage state in our functional components. With Hooks we can manage state in our components pretty easily, and also share state logic, making our code more readable and our application more concise.

Hooks?

The way we deal with the state in React was always such a big topic and a point of a lot of discussion from developers. The fact that we should use ES6 classes to deal with the state was kind of annoying because we weren’t too acquainted with it, and we were always seeking some solution for it. Now with Hooks, we have a whole new way to deal with the state to React.

Hooks allow us to deal with our state with functional components, so now there’s no need to write more class components. To start to use Hooks, all we need to do is import the useState hook, which is the most important hook:

import React, { useState } from "react";

Now, inside our function component, all we need to do is create a const, which is going to be an array of two values: the first one is our state variable, and the second is our function that’ll do something to our state. Then we pass the useState method and then we pass the default value of our state, which can be an array, object, string, etc.

const [name, setName] = useState("");

I just defined a state called name, which is going to be a string. With setName, I can set my name every time I call it. Pretty simple and powerful, we can do everything that we were doing with ES6 classes now with functional components. But you might be wondering how we can deal with lifecycle methods inside a functional component.

For this, the React team released the useEffect hook, which can totally replace the lifecycle methods that we were using in ES6 class components, it allows us to create some side effects in our components. To use it we need first to import it:

import React, { useState, useEffect } from "react";

And inside our functional component, we pass a function called useEffect.

Similar to componentDidMount and componentDidUpdate, everytime we render this component it’s going to render our name state that we defined earlier:

useEffect(() => { console.log(name); });

The useEffect hook can be very tricky because there’s a lot of ways to use it. Using it the wrong way could create some problems in your application. I’d really recommend that you first read the documentation about the useEffect hook, and then, to see how it works under the hood, read this post written by Dan Abramov that explains everything about the useEffect hook.

This was a brief introduction to Hooks. Next we’re going to learn about Custom Hooks, what are they, why they’re so powerful to manage state logic in our applications, and how we can replace our High Order Components our Render Props with them.

Custom Hooks

Hooks really came to solve the problems that we have with High Order Components and Render Props, and also to allow us to deal with the state with a better way than with classes components. We can create Custom Hooks to use everywhere in our application, share our state logic when we want and have a better component composition. Custom Hooks are basically a function, so we can import it everywhere we want. In the last article, we created a render prop called FetchJoke, and we know that a render prop is basically a prop whose value is a function, so we pass a component to this prop and it renders to us.

Now, we’re going to replace this render prop with a Custom Hook, and you’re going to see how Hooks can be a better, more powerful and readable way to deal with code reuse and component composition cases in React than HOCs and Render Props.

Let’s create a file called useJokes, which is going to be a file where we’re going to create our custom hook. Now, let’s import the useState hook, create an arrow function called useJokes, and export it at the end of our file.

import { useState } from 'react';

const useJokes = () => {
  // ...
}

export default useJokes;

So now, inside our useJokes function, let’s create our state, which is going to be called joke. And we’ll also create a function to set our state every time we make a request, which is going to be called setJoke. We’re going to pass a default value to our joke state which is going to be ‘No joke.

const [joke, setJoke] = useState("No joke.");

Now that we implemented our state, we need to create our onRequest function, where we’ll make a request when we click the button. So below our state, let’s create an arrow function called onRequest and pass our request inside it:

const onRequest = () => {
  fetch("https://api.chucknorris.io/jokes/random")
    .then(response => response.json())
    .then(joke => setJoke(joke.value))
    .catch(err => err);
};

Notice that when we return the whole joke, which is going to be an object, we need to set a joke with the setJoke function and pass the joke.value for it. Otherwise, it’ll throw an error.

Well now our Custom Hook is almost done. All we need to do is return the joke and the onRequest at the end of our function like this:

return { joke, onRequest };

And our whole Custom Hook has only 16 lines and looks like this now:

import { useState } from "react";

const useJokes = () => {
  const [joke, setJoke] = useState("No joke.");
  const onRequest = () => {
    fetch("https://api.chucknorris.io/jokes/random")
      .then(response => response.json())
      .then(joke => setJoke(joke.value))
      .catch(err => err);
    };
    return { joke, onRequest };
};

export default useJokes;

Now with this Custom Hook, we can replace our High Order Component and our Render Prop pretty easily. All we need to do is import our useJokes inside our Jokes component, and inside our component put the following code:

const { joke, onRequest } = useJokes();

Next, inside our return method, we’re going to return this:

<div>
  <h4>{joke}</h4>
  <button onClick={onRequest}>Click to see a new joke.</button>
</div>

Every time we click the button, it’s going to return to us a new joke. You can notice that the code gets cleaner and more readable, which helps us to understand what’s going on under the hood.

Advanced Patterns

Now that we have Hooks and are able to create Custom Hooks, a lot of people might be wondering: ‘Are Render Props dead now?’ or, ‘Is it worth it to use Render Props?’ And my answer would be NO to both questions.

Render Props are not dead, but I don’t think that is it worth using Render Props now that we have Hooks. We know that a Render Prop is a prop whose value is a function, but using Render Props we might face some problems, and one of those is Wrapper Hell. Look at this example:

<Connect render={({ loading, user }) => (
  <User render={({ id, name, list}) => (
    <Details render={({ id, name, text}) => (
      <!-- ... -->
    )} />
  )} />
)}/>

In this case, I just passed an example in which we only have 3 Render Props, but it can get worse quickly and our code can get pretty messy and slow. And this problem is not exclusive to Render Props - we might face this problem using High Order Components:

connect(withLoading(withHandler(withProps(TodoComponent))));

In this case, we’re using only 4 HOCs to pass our logic to our component, but let’s imagine that we have a case that we should use 10 or more HOCs nested. It would be pretty painful and very slow to develop and maintain this code. By using Hooks, we do not have this problem because all of our logic is shared between our components and we’ll never have some problem like Wrapper Hell using Hooks.

This doesn’t mean that you should use Hooks in all cases and never go back to High Order Components or Render Props! It means that in some cases (and in the vast majority of them), it’s better to use Hooks because it can aggregate a lot of your application, helping your code become more readable, faster, and reused far more.

Conclusion

In this two-part series, we learned about Advanced Patterns to React and also learned how to replace them with Hooks. The future of React now will be more and more Hooks - with better component composition throughout our applications, state logic being really easy to share between components, better code readability, less messy and slow code, etc.

If you have any pros and cons against Advanced Patterns or Hooks, comment below and let’s discuss it and improve the future of React patterns and composition.

Thank you for reading!

 

Curious for More on Using React Hooks?

For further reading on React Hooks, check out some of these related posts:


Leonardo Maldonado
About the Author

Leonardo Maldonado

Leonardo is a Full Stack Developer, working with everything React-related, and loves to write about React and GraphQL to help developers. He also created the 33 JavaScript Concepts.

Related Posts

Comments

Comments are disabled in preview mode.