I was recently introduced to the React Hooks api. It seems to be quite interesting and has potential to completely change how we make React apps.

Introduction:

NOTE: Its an alpha release, so please do not use it in large scale production applications for now. But I do not feel that its going to be that way for long.

You can find the documentation here. Briefly, the api aims to help in following ways:

Reducing the use of classes as they seem to be confusing the programmers who have used them extensively in other languages

Separating the concerns in a component’s code based on logic instead of lifecycle methods — no more duplication of code in componentDidMount and componentDidUpdate

and Using the stateful logic across components in an isolated manner without having to use higher-order components or render-props

Implementation:

We need to think of a better example application to check out new stacks, as a todo-list is becoming very easy and doesn’t always cover all the elements we want to try out. In this case however, I mostly wanted to checkout the useReducer() hook. It would be nice to be able to re-use most of the reducer code that we have in our applications already. So, todo-list works for me.

Basic setup:

One can use the usual create-react-app and get going pretty quickly, but I suspected there might be some library version mismatches. So, I went with a barebones setup from scratch. There was indeed a hiccup in getting HMR working (needs atleast v4.6.0):

Install a package manager like yarn (or npm ) if not already installed

(or ) if not already installed Initialise the application with yarn init (and git init )

(and ) Make public and src folders in the application directory

and folders in the application directory Add a .gitignore with the usual items like node_modules and dist

with the usual items like and Add a basic index.html in the public folder:

Install babel: yarn add --dev @babel/core@7.1.0 @babel/cli@7.1.0 @babel/preset-env@7.1.0 @babel/preset-react@7.0.0

Add a .babelrc with following:

{ "presets": ["@babel/env", "@babel/preset-react"] }

Install webpack dependencies: yarn add --dev webpack@4.19.1 webpack-cli@3.1.1 webpack-dev-server@3.1.8 style-loader@0.23.0 css-loader@1.0.0 babel-loader@8.0.2

dependencies: Add a webpack.config.js to the application directory:

Add a React dependencies: yarn add react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2 react-hot-loader@4.6.0

Add an index.js to the src folder:

Add an App.js to the src folder (Keep the todo-list part commented for now. We will uncomment these once we have made them. Its always better to get the app working first.):

Add scripts to the package.json :

"scripts": {

"start": "webpack-dev-server --mode development",

"build": "webpack --mode production"

}

Run the application with yarn run start and verify if the app with HMR is working as expected at localhost:3000 .

Todo-list:

The premise was that we want to use the reducer code as it might already exist in a React app. So, lets add the reducer first the then work on using it within the application.

One can have an even simpler logic for a todo-list reducer using just the indices everywhere, but from personal experience I’ve found using ids safer.

Coming to the hooks, we will be using useReducer and useState in this example. You can find their documentations here and here.

useReducer is defined like this:

const [state, dispatch] = useReducer(reducer, initialState);

This might look very familiar to people who have been using reducers in React applications for while. state is the normal state of the component; dispatch is used to call an update to the state ; reducer defines the update logic; initialState declares the value for the state to be initialised with.

In our example, the parent component that holds the todo-list logic would declare the state using useReducer and pass along CRUD functions, that would be using dispatch , to the child components.

2. useState is defined like this:

const [state, setState] = useState(initialState);

Here, state can be any variable that you might otherwise declare using this.state in a constructor. initialState is the initial value for that variable. setState works in a way similar to this.setState , but its specific to the variable being declared here. In conjunction with useEffect hook (mainly for handling operations on mount and update; not used in this example), ideally following this declaration, this would group the entire logic related to the variable state in one place within the component code. If it needs to be used in multiple components, this logic can be wrapped in a custom hook as well.

In our example, the CRUD operations on todos are handled by the props that are passed to children from the parent component. But, the local handling of a todo text update can be handled by useState .

There was very little logic involved in handling the text and mode update. In case of real world applications, there will be more logic attached to it, like having varying permissions on modes available and requiring authentication check before edit. In such cases, it would be wise to move the mode and text edit logic into custom hooks, and use across components.

Style and run:

As a final touch, lets add some styling to our components here.

And, we are done. This is how the application looks like:

The code for this example is available at: https://github.com/nsuthar0914/react-hooks-webpack-hmr

Observations:

This approach might lead to much more readable and dry code

It can be used in parallel to existing code without necessarily updating all of it

Its quite easy to get hooked to it

Looking forward to trying out more of this and see how it works with GraphQL clients.

— Neeraj Suthar