With React Conf 2018 behind us, we have learned that with release 16.7 of React, an important new feature will be available: React Hooks. Join me as we go through working examples and get "hooked" on React.
We are watching React slowly become more opinionated, and with the latest features, I would dare to say it's becoming more like a framework than ever before. React has typically been known to be less of a fully featured framework and more of a library that lets you render DOM and manage its state really well. The ecosystem has a few tools that are opinionated and still widely used as standard in a lot of React apps, like Redux for instance. Now Hooks are not Redux, but they are an alternative way of doing things for those who recently found Redux, which builds on the Flux pattern as a requirement for every application to mange state.
I believe that Hooks are a bridge to Redux but also a way of managing simple state without introducing Redux. It makes total sense that Dan Abramov was the one who showed us our first working example at React Conf 2018 as he is also the creator and main contributor to Redux. I think this lends credibility in some way towards the use of Hooks and indicates they are thinking about how to bring better state management into React core, and how to also ensure that Hooks will compliment and make use with Redux a priority.
With the introduction of things like code splitting, suspense, lazy, memo and now hooks, I think that the changes we have seen in 2018 are done with the developer and performance in mind. Competition with other frameworks is also becoming a reality. This competitive environment I believe is what is forcing React to become more of a lightweight framework. And if we are going to see a more opinionated React with framework-like features, I'm really happy about how the React team is going about these latest additions to the API. I asked a few people if they thought React was becoming a framework, a few said yes, one person just sighed, and another said, until they make the router part of React, I don't consider it a framework.
With React Conf 2018 behind us, we have learned that with release 16.7, a new feature will be available: React Hooks.
Currently you can read about the Hooks, view the RFC (Request for Comments) and play around with the new feature using: npm install react@next react-dom@next. Hooks represent a strictly additive feature to React that introduces no breaking changes, meaning it's completely opt-in. It provides an alternative to writing class based components simply to use state and access life-cycle methods.
npm install react@next react-dom@next
Because Hooks will be implemented with a gradual adoption strategy (living side-by-side with existing code), it gives teams time to refactor their code or simply leave the legacy code alone as they introduce new functional components using Hooks. Hooks have already been dubbed: "The Future of React," but it is also noted that classes will be supported for the foreseeable future. Hooks bring to functional components the things we once were only able to do with classes. Like being able to work with state, effects and context specifically.
In the past, some React developers have experienced confusion around when to use and when not to use classes. @SophieBits commented in the "React Today and Tomorrow" talk that classes can be "hard for humans and machines as well." I think we will see more of this move away from classes whenever possible. It's actually the right thing to do in some cases - the stance on this goes back years with talks like: "How to Sleep at Night using React Classes," even though we must sometimes use them in the current React. But that issue is being handled now and we already see developers having strong opinions and using mostly functional components when and where they can.
Hooks give functional components the upper hand in React. Some of the additional Hooks already available in the React API (16.7.0-alpha) include: useReducer, useCallback, useMemo, useRef, useImperativeMethods, useMutationEffect, useLayoutEffect, uhh did I get them all? Just driving the point home, this is useful stuff!
The easiest way to describe Hooks is to simply show you two examples, one being a class component that needs to have access to state and life-cycle methods and another example where we achieve the same thing with a functional component. I have read through the proposal for Hooks and for this reason I will use a similar code sample that Dan Abramov uses in the docs.
You could just read the docs, and I suggest doing so. However, I wanted to provide you with a working example that you can touch and feel and play around with. I learn best by getting my hands dirty. For this reason I wanted to provide the same examples illustrated in the docs, but with a StackBlitz demo for each stage so that you can test it out for yourself.
This GIF below shows the difference between the Class and Functional Component example we will see in the next section:
Below we follow the canonical counter example provided in the React docs. It contains a button inside of a Counter component. Once clicked, it advances the state by one and updates the state.count for rendering purposes.
First we see how to do this with a class based component using just setState :
The first thing to notice about the class-based component is that the class syntax uses a constructor that references the this keyword. Inside the constructor we have a state property. We also update the count using setState().
Now, lets see how to do the same thing with Hooks, using a functional component:
In the functional component example we have an additional import of useState. There's no more class syntax or constructor, just a const. Its assignment sets the default and provides not only the count property, but a function for modifying that state called setCount. This setCount refers to a function and can be named whatever you like.
The functional component incrementCount method is easier to read, and references our state value directly instead of referencing this.state.
When updating state, we sometimes have side effects that need to happen along with each change. In our example of the counter, we may need to update the database, make a change to local storage or simply update the document title. In the docs, the React team chose the latter example to make things as simple to understand as possible. So let's do just that and update our examples to have a side effect that uses the new Hook useEffect.
Let's add this side effect to our existing counter example and again look at the old way of doing this with Classes vs working with Hooks. We will first see how to do this with a basic class-based component:
And next how to do the same thing with Hooks:
Now that we are introducing additional behavior, we start to see even more evidence of how switching to Hooks provides a cleaner way of dealing with state and side effects. What took two separate life-cycle methods in the class component we can achieve with just one call to useEffect. We do have one more import on the functional component example, but if we can get rid of the class syntax, an additional life-cycle method and make our code cleaner and more readable, it's totally worth it.
Just like with setState, you can call useState as many times as you want. Let's switch to an example that shows a slightly more involved situation where we have a name we are displaying on the page, some inputs that allow for the name to be changed, and we want control over both the first name and the last name. We can create two separate properties, each with their own update or set function, and simply call useState on each in order to set the default.
In the GIF below, you can see what this would look like - as well as what it looks like with a class-based version, which we'll dig into a little more below.
As you would expect we also have an update function for each name so that you can handle changes to them independently.
Let's see the code for the class-based component:
And now the same thing with Hooks:
I won't go over all the differences again, but I wanted you to see a slightly more complex example side-by-side. Hopefully you are starting to see the benefit of using Hooks.
Let's make one more change to this example and use useEffect to save our name to local storage so that we don't lose our state when we refresh the page.
Let's see the code for the class-based component:
I hope that these interactive examples allow you to understand the basics of setState and useEffect. I plan to release more articles on the subject of React Hooks as well how to use them with our KendoReact native React components. If you are new to React, we have more content here on the Telerik blog specifically around All Things React, which contains a plethora of information about React and its ecosystem. Please explore our articles and products and let me know if you have any questions or ideas for articles on subjects relating to React.
Thanks for taking the time to read about React Hooks - below is additional information around the topic that you can find online!
React Docs on Hooks
Making Sense of React Hooks
Understanding Hooks in React a Deep Dive
A Simple Intor into Hooks
React 16.7 Hooks Tutorial
Flux Without Fuss: From Containers to Hooks
React Conf 2018 Day One Talks
Share Complex Logic across React Components with Custom Hooks
Access and Modify a DOM Node with the React useRef and useEffect Hooks
Share Logic Across Multiple React Components with Custom Hooks
Use the useState React Hook
Test React Components that use React Hooks
React Hooks a Complete Introduction
TODO List with Hooks
Eric Bishard is a Developer Advocate working with KendoReact here at Progress. As a software engineer, he has experience building web based applications with a focus on components for user interfaces in frameworks like Angular and React. Feel free to connect with Eric (@httpJunkie) on Twitter!