A Todo list with React Hooks !
Hi all! In this article we will have look into the new experimental Hooks API feature that are going to be shipped in React soon, which is available in React v16.7.0-alpha. We will write a simple todo list application as example by using some of the new APIs for the built-in hooks such as: useState
, useReducer
and useContext
.
Before starting looking into the code let’s get a brief introduction on React Hooks.
What are React Hooks ?
On the official webpage at https://reactjs.org/docs/hooks-intro.html facebook says:
Hooks are an upcoming feature that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha.
and continues explaining one of the most known “problem” with React:
React doesn’t offer a way to “attach” reusable behavior to a component. If you’ve worked with React for a while, you may be familiar with patterns like render props and higher-order components that try to solve this. But these patterns require you to restructure your components…
So they came to a conclusion that React needs a better primitive for sharing stateful logic and you know what? Hooks will support us soon in that.
With Hooks, in fact, stateful logic can be extracted from a component and reuse it without changing your component hierarchy. This makes it easy to share Hooks among many components or with the community.
For more details I would suggest you to have a full read on hooks introduction available at https://reactjs.org/docs/hooks-intro.html.
Let’s start look into the code now !
On the Redux web site at https://redux.js.org/basics/example you can see an example on how implementing a todo list using React+Redux.
I have written the same example by using React Hooks instead.
Entry Point
index.js
We will use React.createContext
along with the Hooks to provide the same context to all its children thanks to <TodoContextProvider />
component.
Contexts
contexts/todos.js
- Line 12: as you can see the
useReducer
Hooks API is invoked. Nothing to be scared of, if you’re familiar with Redux, you already know how this works. TheuseReducer
function takes as input three args a functionreducer
, an objectinitialState
and an optional third argumentinitialAction
. What it returns is an array in which the first element is the state reduced bytoDoReducer
function and as second element a functiondispatch
for performing actions.
Each time an action is performed invoking the dispatch
method by any of its children it will cause a re-rendering of TodoContextProvider component which gets the new state and propagates the updated value to all its children.
How can have access to the dispatch function and to the state object?
The new Hook useContext
API will help on this avoiding us to nest Context.Provider across our components.
As you can see by looking at the code below the only thing we have to do for getting the context is to provide to the useContext
Hooks API a valid Context generated through the React.createContext
API, which we have already done in the contexts/todos.js
( see above ).
Use the Context
components/Todo.js
As you surely noticed the <TodoContextProvider />
is providing to all its Consumers an object named value.
const value = {value, dispatch};
- Line 7: the
useContext
Hooks API is getting that context avoiding us to pass down a propsdispatch
to each children or wrapping our Todo Component within a ContextConsumer as we were used to do:
<TodoContext.Consumer>{ context => <Todo context={context} />}</TodoContext.Consumer>
Any child at any level in the tree inside <TodoContextProvider />
can use the dispatch
function to perform actions and the state
too. It is awesome, isn’t it?
What about useState? We did not see it around the code yet?
There it is !!! line number 9.
components/AddTodo.js
- Line 9:
useState
is a Hook which if called inside a function component it adds some local state to it. It takes an argument theinitialState
and returns the current statevalue
and a function in our case namedsetIndex
which accepts a new state valuesetIndex(newValue)
and once called it updates the prevState causing a re-rendering of the component. After the re-rendering, the first value returned byuseState
in our casenextTodoId
will be the most recent state after applying updates. - Line 40:
useFromInput
is a custom Hook which it has been used to control the<input />
element.
At this point I would invite you to have a look into the repo linked below in which you can find the full source code.
A live example can be run in your browser via CodeSandBox.
Conclusions
As I said React Hooks are still experimental features which according to Facebook will be released around the Q1 2019 https://reactjs.org/blog/2018/11/27/react-16-roadmap.html , the APIs we looked into this article might change, so you should not rewrite your application by using hooks yet.
After few hours playing with Hooks I personally think that features like stateful logic separation or sharing context across your components without the necessity to wrap the your components around Context Consumers will make code more readable and simpler to test. I also did not find a big learning curve to face, after reading the docs it was quite straightforward.
Hope you enjoyed the article and it was useful to give you a better understanding on the new way we are going to write React Components.
So try them out and let me know what you think about them!