React hooks: Creating stateful components without Class and the impact on design patterns

Programming languages and frameworks are always changing. React, the most popular framework amongst the JavaScript community, is no exception. With the introduction of  hooks, you can now use state and other React features without writing a class. In the official documentation, hooks are explained as:

Functions that let you “hook into” React state and lifecycle features from function components. Hooks don’t work inside classes — they let you use React without classes.

Ultimately, hooks were designed with code reuse in mind but that’s not all. Hooks are also here to replace class components and the frustrations that come with them, however, hooks now provide a new way to create components, so some of those tried and true React design patterns will now need to be implemented with hooks.

React design patterns and the intro of hooks

React design patterns are great for a few reasons:

  • You’re able to think more abstractly about how you create applications in React.
  • They help you organize and simplify large React applications so you can build separate components and share logic between them.
  • React patterns are tried and tested methods for building reusable components that don’t cripple flexibility.

Some of the most popular design patterns are compound components, higher-order components (HoC), and render props. Now that hooks have been brought into the picture, certain React patterns have gone out of favor including HoCs and render props. They have not been removed from the framework (and it doesn’t seem like React will remove them) but developers are starting to favor hooks and here’s why:

  • Hooks don’t introduce unnecessary nesting into your component tree.
  • Hooks don’t suffer from drawbacks of mixins.
  • Hooks reduce the amount of duplicated logic between components

While some patterns are going out of favor, they can still be implemented with hooks. Check out Advanced React Patterns with Hooks to learn how you can recreate the famous patterns developed by Kent C. Dodds by using hooks.

React components and the intro of hooks

There are two main types of components in React and they are functional components (stateless) and class components (stateful). Both have their advantages and drawbacks. Functional components are typically easier to test, write, and read but they lack some features like the ability to hold state. Class components include features like lifecycle hooks and the ability to hold local state, but they are confusing for both machines and humans.

Class components, although useful, bring about some unexpected challenges that functional components don’t introduce. To name a few, class components make it difficult to separate concerns, you end up with confusing classes, and an overuse of wrappers.

But what if I want to use functional components and still keep the features that class components offer?

This is where hooks come in. Hooks allow you to use functional components (the preferred method for creating components) with all the bells and whistles that class components offer. With hooks, you’re able to share logic inside a component as opposed to between components,  making separation of concerns less of a worry. Now you’re able to write clean, reusable code that lets you create stateful components without the use of class.

Built-in and custom hooks

React comes with built-in hooks like useState and useEffect just to name a few.

useState is called inside a function component to add local state to it, which will be preserved between re-renders. useState returns a pair: the current state value and a function that lets you update it. You can call this function from an event handler or somewhere else. It’s similar to this.setState in a class, except it doesn’t merge the old and new state together.

Side effects are common in React; things like data fetching, subscriptions, or manually changing the DOM are things we are used to doing. The useEffect hook makes it easy to perform side effects right from a function component. Remember componentDidMount and componentDidUpdate from a class? useEffect accomplishes the same goal as these but it’s unified into a single API.

React also gives you the freedom to leverage built-in hooks to create your own custom hooks. You can write custom hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, and more, making functional components even more powerful.

So what about HoCs and render props patterns?

You can continue to use HoCs and render props, but hooks are preferred. Most use cases involving these patterns deal with rendering only a single child, so it’s not ideal to use these patterns because they can become complex and introduce nesting in your tree. More often than not, hooks will be the means to accomplish what these patterns do.

What design patterns are still relevant?

While some design patterns are on their way out, others are still very much accepted by the community and can be reproduced using hooks. These patterns include:

  • Compound components
  • Control props
  • Props collection
  • Prop getters
  • State initializer
  • State reducer

Get started with React hooks and learn how to refactor these patterns to fit the hooks model.

Conclusion

Hooks are a relatively new feature that are designed to solve most of the problems that class components suffer from. They do however have an impact on the patterns that developers have been using to create applications, meaning you’ll have to learn how to implement these patterns with hooks, and if not now, eventually.

It’s been recommended that you gradually shift towards the hooks model. There is no reason to rip and replace your code now, but it is worth experimenting in new projects.

Happy learning!

Show Comments