React Hooks Tutorial Beginner Level

Purpose of this Blog:

To explain how React Hooks work

Build a simple Application to help in understanding

What we are Building

A simple Todo app where we can add todo items, mark todo items as complete and delete todo item

Get started

React Hooks are a new addition in react version 16.8.0, we are going to learn about the 'UseState' Hook. The biggest addition that Hooks add is giving us the ability to use state in function based components we all know this was not possible before. This hook lets you have an internal state inside a functional Component

Lets create a React app

cd into your Preferred directory

in the command line run $ npx create-react-app react-hook-tutorial

Then we cd into the above cd react-hook-tutorial

Open your code editor and let us delete the existing code in App.js and App.css

lets write code.

In this tutorial, We are going to use mock Data our objective will be to display the data. We will be using semantic UI for styling I am using the CDN

In the index.html file add < link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/1.11.8/semantic.min.css" />

In our App.js file Lets add this

import React, { useState } from "react" ; import "./App.css" ; function App ( ) { const [todos, updateTodo] = useState([ { item: "learn react hooks" , completed: false }, { item: "create a simple app to illustarate the above" , completed: false }, { item: "push to git hub" , completed: false } ]); return ( < div id = "role" role = "list" className = "ui divided relaxed list" > < div role = "listitem" className = "item" > {todos.map((todo, index) => ( < Todo key = {index} index = {index} todo = {todo} /> ) )} < /div> </ div> ); } export default App;

Now we create a components folder inside the src folder, create a todo.js file

add the following

import React from "react" ; const Todo = ({ todo, index, }) => { return ( < div role = "list" className = "ui divided middle aligned list" > < div role = "listitem" className = "item" > < div className = "right floated content" > </ div > < i aria-hidden = "true" className = "spinner loading icon" /> < i aria-hidden = "true" className = "certificate loading icon" /> < i aria-hidden = "true" className = "asterisk loading icon" /> < div className = "content" > {todo.item} </ div > </ div > </ div > ) ; }; export default Todo;

Now we have our Todo component which we need to use in our App.js file

Add this in our App.js file

import Todo from "./components/todo" ;

Open your browser and you should have something similar to what we have. You can use any image for your background image

We have been able to display our todos. We will now start using the useState Hook. We want to be able to add a new todo item. In the components, folder create a file addTodoForm.js

Add the following code

import React, { useState } from "react" ; function AddTodoForm ( { addTodo } ) { const [value, setValue] = useState( "" ); const handleSubmit = e => { e.preventDefault(); if (!value) return ; addTodo(value); setValue( "" ); }; return ( < form className = "ui success form" > < div className = "field" > < label > Add Todo Item </ label > < div className = "ui input" > < input type = "text" placeholder = "Add todo item" value = {value} onChange = {e => setValue(e.target.value)} /> </ div > < button onClick = {handleSubmit} className = "ui button" > Add </ button > </ div > </ form > ) ; } export default AddTodoForm;

The above code only gives us a form we are not able to add a todo item yet. So at this point, we need to write the addTodo function that will make this possible. Remember we passed it as a prop in the component we have created above.

Add the following in the App.js file

const addTodo = item => { const newTodos = [...todos, { item }]; updateTodo(newTodos); };

We will still not be able to add a todo item, to make this happen we need to import the addTodoForm in our App.js file

Open App .js and lets add

import AddTodoForm from "./components/addTodoForm" ;

lastly add this <AddTodoForm addTodo={addTodo} />

Now our App.js file Looks like this

import React, { useState } from "react" ; import "./App.css" ; import Todo from "./components/todo" ; import AddTodoForm from "./components/addTodoForm" ; function App ( ) { const [todos, updateTodo] = useState([ { item: "learn react hooks" , completed: false }, { item: "create a simple app to illustarate the above" , completed: false }, { item: "push to git hub" , completed: false } ]); return ( < div id = "role" role = "list" className = "ui divided relaxed list" > < div role = "listitem" className = "item" > {todos.map((todo, index) => ( < Todo key = {index} index = {index} todo = {todo} /> ) )} <AddTodoForm addTodo={addTodo} /> </ div > </ div > ) ; } export default App;

At this point, we should have a form to add a new todo item. You should have something similar to what we have below.

We now need two buttons one to mark a todo as complete and another to delete a todo item

Open the todo.js file and add the following

< button onClick = {() => completTodo(index)} className="ui button"> Complete </ button > < button onClick = {() => deleteTodo(index)} className="ui button"> Delete </ button >

The todo.js file should now look like this

import React from "react" ; const Todo = ({ todo, index }) => { return ( < div id = "main" style = {{ textDecoration: todo.completed ? " line-through " : "" }} role = "list" className = "ui divided middle aligned list" > < div role = "listitem" className = "item" > < div className = "right floated content" > < button onClick = {() => completTodo(index)} className="ui button"> Complete </ button > < button onClick = {() => deleteTodo(index)} className="ui button"> Delete </ button > </ div > < i aria-hidden = "true" className = "spinner loading icon" /> < i aria-hidden = "true" className = "certificate loading icon" /> < i aria-hidden = "true" className = "asterisk loading icon" /> < div className = "content" > {todo.item} </ div > </ div > </ div > ) ; }; export default Todo;

Notice in both the complete button and delete button we called a completeTodo function and a deleteTodo function respectively, these functions don't exist so we have to create them

Open App.js and add the following block of code

const completTodo = index => { const NewTodos = [...todos]; NewTodos[index].completed = true ; updateTodo(NewTodos); }; const deleteTodo = index => { const NewTodos = [...todos]; NewTodos.splice(index, 1 ); updateTodo(NewTodos); };

Then add this in the App.js file

completTodo={completTodo} deleteTodo={deleteTodo}

our App .js file now looks like this

import React, { useState } from "react" ; import "./App.css" ; import AddTodoForm from "./components/addTodoForm" ; import Todo from "./components/todo" ; import HeaderDiv from "./components/header" ; function App ( ) { const [todos, updateTodo] = useState([ { item: "learn react hooks" , completed: false }, { item: "create a simple app to illustarate the above" , completed: false }, { item: "push to git hub" , completed: false } ]); const addTodo = item => { const newTodos = [...todos, { item }]; updateTodo(newTodos); }; const completTodo = index => { const NewTodos = [...todos]; NewTodos[index].completed = true ; updateTodo(NewTodos); }; const deleteTodo = index => { const NewTodos = [...todos]; NewTodos.splice(index, 1 ); updateTodo(NewTodos); }; return ( < div id = "role" role = "list" className = "ui divided relaxed list" > < HeaderDiv /> < div role = "listitem" className = "item" > {todos.map((todo, index) => ( < Todo key = {index} index = {index} todo = {todo} completTodo = {completTodo} deleteTodo = {deleteTodo} /> ) )} <AddTodoForm addTodo={addTodo} /> </ div > </ div > ) ; } export default App;

Lastly, to be able to use the two functions we need to pass them as props in the todo.js file. Open it and add this

const Todo = ({ todo, index, completTodo, deleteTodo })

Now the todo.js file looks like this

import React from "react" ; const Todo = ({ todo, index, completTodo, deleteTodo }) => { var buttonText = todo.completed ? "completed" : "complete" ; return ( < div id = "main" style = {{ textDecoration: todo.completed ? " line-through " : "" }} role = "list" className = "ui divided middle aligned list" > < div role = "listitem" className = "item" > < div className = "right floated content" > < button onClick = {() => completTodo(index)} className="ui button"> {buttonText} </ button > < button onClick = {() => deleteTodo(index)} className="ui button"> Delete </ button > </ div > < i aria-hidden = "true" className = "spinner loading icon" /> < i aria-hidden = "true" className = "certificate loading icon" /> < i aria-hidden = "true" className = "asterisk loading icon" /> < div className = "content" > {todo.item} </ div > </ div > </ div > ) ; }; export default Todo;

Notice I introduced a buttonText variable this is just to make the text in the button dynamic that is if you click on the button the text becomes completed

Lastly we will add an about section In the components, folder create a file header.js and add the following block of code

import React from "react" ; function HeaderDiv ( ) { return ( < div className = "ui message" > < div className = "header" > About </ div > < p > This is a simple application to help you level up on React Hooks. There is no data persistence as this will be available in the next tutorial. </ p > < p > Below are links to the developers LinkedIn and Github accounts respectively </ p > < a href = "url" > < button className = "ui linkedin button" > < i aria-hidden = "true" className = "linkedin icon" /> LinkedIn </ button > </ a > < a href = "url" > < button className = "ui github button" > < i aria-hidden = "true" className = "github icon" /> github </ button > </ a > </ div > ) ; } export default HeaderDiv;

We then bring in the component, open App.js and add the following import statement

import HeaderDiv from "./components/header" ;

Now our App.js file should look like this

import React, { useState } from "react" ; import "./App.css" ; import AddTodoForm from "./components/addTodoForm" ; import Todo from "./components/todo" ; import HeaderDiv from "./components/header" ; function App ( ) { const [todos, updateTodo] = useState([ { item: "learn react hooks" , completed: false }, { item: "create a simple app to illustarate the above" , completed: false }, { item: "push to git hub" , completed: false } ]); const addTodo = item => { const newTodos = [...todos, { item }]; updateTodo(newTodos); }; const completTodo = index => { const NewTodos = [...todos]; NewTodos[index].completed = true ; updateTodo(NewTodos); }; const deleteTodo = index => { const NewTodos = [...todos]; NewTodos.splice(index, 1 ); updateTodo(NewTodos); }; return ( < div id = "role" role = "list" className = "ui divided relaxed list" > < HeaderDiv /> < div role = "listitem" className = "item" > {todos.map((todo, index) => ( < Todo key = {index} index = {index} todo = {todo} completTodo = {completTodo} deleteTodo = {deleteTodo} /> ) )} <AddTodoForm addTodo={addTodo} /> </ div > </ div > ) ; } export default App;

That brings us to the end of the tutorial

Demo Link

Full code

For a deeper understanding of React hooks click here

This is how the product looks like