DEV Community

mitchel inaju
mitchel inaju

Posted on • Originally published at mitchel.hashnode.dev on

Getting Started With React Hooks

What are React Hooks?

In the React 16.8 version, hooks are the new functionality. It permits the use of state and other React features without the need to create a class. In the past, you'll have to write class-based components to perform some of these methods.

Hooks are JavaScript functions that manage the state's behavior and side effects by isolating them from a component. React hooks allow you "hook into" react features and are not permitted when using class-based components.

Does React Hooks give me superpowers?

Short Answer: No

Long Answer: Hooks are not a replacement for understanding React fundamentals. Hooks instead offer a more direct API to the React concepts you are already familiar with, including props, state, context, refs, and lifecycle. Hooks also provide a fresh, potent approach to combining them.

Why should I learn about hooks?

  1. Reuse of Stateful Logic between related or unrelated Components'

  2. Escape the complexity of Lifecycle methods

Here's my Point " Hooks let you use more of Reacts features without classes."

Even though you're having a great feeling about hooks, it also has some rules you have to follow through

These rules are:

1. Only call Hooks at the top level

Hooks must be used at the top level of the React functions. Do not call Hooks inside loops, conditions, or nested functions.

2. Only call Hooks from React functions

You cannot call Hooks from regular JavaScript functions. Instead, you can call Hooks from React functional components and Custom Hooks

Basic React Hooks

UseState

This is the simplest hook, it's a Hook that lets you add React state to functional components without needing to transform it into a class component.

Lets look at the snippet below

import React, { useState } from 'react';  

const TapApp=()=> {  
  // Declare a new state variable, which we'll call "tap"  
  const [tap, setTap] = useState(0);  

  return (  
    <div>  
      <p>You tapped {tap} times</p>  
      <button onClick={() => setTap(tap+ 1)}>  
        Tap me  
      </button>  
    </div>  
  );  
}  
export default TapApp;

Enter fullscreen mode Exit fullscreen mode

Here is the result

Let's tap the button

Maybe you're asking what's the use of the square brackets ?

const [tap, setTap] = useState(0);

The arrays on the left are called state variables, and by variables we mean you can change them to something else for our specific use case. The first state variable is the state name and the second is the function for assigning that state. So in this case tapis the variable name and setTap is the function for setting that variable name.

Other similar use cases can include the following

 const [fruit, setFruit] = useState('banana');
 const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

Enter fullscreen mode Exit fullscreen mode

Another question you might have is the 0 between the parenthesis what's it for? can it be changed as well? Yes it can, it's the default value for that state

So let me explain, if you want to render a component ie. when the component first loads up the first state it would show would be the default state

If you've gotten to this part, please note that you already have a basic understanding of how useState hook works, please note that the next section is to apply what you've learnt

Simple Usecase for useState

Since we now fairly have an understanding of how the useState hook work, now let's build a simple inventory store. For this app, I'll be using tailwind to style the app, please click here to get started with tailwind for react.

    const [item, setItem] = useState();
    const [itemInventory, setItemInventory] = useState([]);

Enter fullscreen mode Exit fullscreen mode

We need to set of state variables, item handles the single item while itemInventory handles an array of items(multiple items)

 const handleChange = (e) => {
    setItem(e.target.value)
  }
  const saveItem = () => {
    if (!item) return;
    if (itemInventory.includes(item)) return;
    setItem('')
    setItemInventory(prevValues => {
      return [...prevValues, item]
    }
    )
  }

Enter fullscreen mode Exit fullscreen mode

handleChange function sets the single item state, it's going to be attached to the input element, while saveItem function checks if that particular item is empty and in the itemInventory array, if it's not in the array then it procedes to add that item

<div>
      <div className='flex flex-col gap-y-3 '>
        <div className='mx-auto space-y-3 mt-4'>

          <label for="fruitInput" className='text-3xl text-center'>Please enter your Items</label>
          <div className='flex space-x-2'>
            <input
              placeholder='water bottle...'
              className='w-80 p-2 px-4 border-2 border-slate-100 rounded-md focus:outline-slate-400 '
              name="fruitInput" value={item} onChange={handleChange} />
            <button onClick={saveItem} className='rounded-md w-fit p-2 bg-slate-100 hover:bg-slate-200 active:text-slate-100 '>+ Add</button>
          </div>
        </div>
        <div className='flex max-w-[1000px] flex-wrap gap-4 mx-auto mt-10'>

          {itemInventory.map((i, v) => (
            <ItemCard item={i} />
          ))}
        </div>
      </div>
    </div>

Enter fullscreen mode Exit fullscreen mode

Here we set the value of the input to item and it's onChange to handleChange, we're also assigning the onClick function to the saveItem function we just created, so that when we click on the button it triggers the saveItems function that adds that particular item to the array.

We are also mapping through the itemInventory state with the ItemCard component

ItemCard.jsx

import React, { useState } from 'react';

function ItemCard({ item }) {

    const [totalNumber, setTotalNumber] = useState(0)

    const handleRemove = () => {
        if (totalNumber > 0) {
            setTotalNumber(totalNumber - 1)
        }
    }
    const handleAdd = () => {
        setTotalNumber(totalNumber + 1)
    }

    return (
        <div className='w-[300px] bg-black/[0.05] hover:bg-slate-100 h-1/3 p-10 '>
            <p className='font-bold text-2xl text-gray-700'>
                {item}
            </p>
  <p className='font-semibold text-lg text-gray-500'>Total:{totalNumber}</p>
            <div className='flex gap-2'>
                <button className='w-fit bg-gray-500 text-white p-1 px-2 rounded-md' onClick={() => handleAdd()}>Add</button>
                <button className='w-fit bg-gray-500 text-white p-1 px-2 rounded-md' onClick={() => handleRemove()}>Remove</button>
            </div>
        </div>
    )
}

export default ItemCard

Enter fullscreen mode Exit fullscreen mode

ItemCard helps us to set the total number present for that particular item, so for example, I add an item called "phone" ItemCard.jsx helps us visualize the item name and also allows us to add and remove the total number present for that item.

So Let's look at the final file

Item.jsx

import React, { useState } from 'react';
import ItemCard from './ItemCard';

const FruitInventory = () => {
  const [item, setItem] = useState();
  const [itemInventory, setItemInventory] = useState([]);
  const handleChange = (e) => {
    setItem(e.target.value)
  }
  const saveItem = () => {
    if (!item) return;
    if (itemInventory.includes(item)) return;
    setItem('')

    setItemInventory(prevValues => {
      return [...prevValues, item]
    }
    )
  }
  return (
    <div>
      <div className='flex flex-col gap-y-3 '>
        <div className='mx-auto space-y-3 mt-4'>

 <label for="fruitInput" className='text-3xl text-center'>Please enter your Items</label>
          <div className='flex space-x-2'>
            <input
              placeholder='water bottle...'
              className='w-80 p-2 px-4 border-2 border-slate-100 rounded-md focus:outline-slate-400 '
              name="fruitInput" value={item} onChange={handleChange} />
            <button onClick={saveItem} className='rounded-md w-fit p-2 bg-slate-100 hover:bg-slate-200 active:text-slate-100 '>+ Add</button>
          </div>
        </div>
        <div className='flex max-w-[1000px] flex-wrap gap-4 mx-auto mt-10'>

          {itemInventory.map((i, v) => (
            <ItemCard item={i} />
          ))}
        </div>
      </div>
    </div>
  );
}
export default FruitInventory;

Enter fullscreen mode Exit fullscreen mode

Result

Default State

Final Result

Final Thoughts

We can see how easy it is to apply what we just learned to a simple inventory app, you can take this knowledge and build out a todo app, or a mini e-commerce application, it's the same principles, although for that you might want to use a more robust solution for handling state.

That's all, if you want to see more details or read about the useState React Hook, please, take a look at the Official Documentation

Reach out to me

Linkedin : https://www.linkedin.com/in/mitchel-inaju/

Twitter: https://twitter.com/mitchelinaju

Top comments (0)