DEV Community

Ahmet Meliksah Akdeniz
Ahmet Meliksah Akdeniz

Posted on • Updated on

useState | One of the Most Common Hooks that You Will Be Using in React

Hello folks, today I will be talking about useState hook in React. Why do we need it? Because useState tracks state in a function component. Whenever data changes, we use useState hook.

Above, I said function component. So, first I will prove useState hook is a function. Copy and paste the code below:

import { useState } from "react";

const ErrorExample = () => {
  console.log(useState);
};
Enter fullscreen mode Exit fullscreen mode

Explanation of code above:
import { useState } from "react"; imported useState function from React. It has to be written exactly like that ({ useState }) because we're importing a specific function from react, otherwise it won't work.

After this open console on your browser (right click on page and click on inspect), you will see this:

react useState first image

So, useState is a function, what does it return?
Invoke the function in console.log, do this console.log(useState());.

react useState second image

As you can see, useState returns an array. First element is a value and second one is a function. We will control the value by using the function inside of this array.

The first element of the array is undefined, the reason for that it doesn't have a default value yet. We can give any type of value we want to this first element (array, object, number, string, boolean... anything really).

react useState third image

I clicked on it to show what f represents

So, how do we give value to that? Even though this is not the only way, I assign values like this
const [value, setValue] = useState(some value | string, array, number); because it's easier using destructuring from JavaScript, and it looks identical to this [undefined, f] return from useState. In my head, I coded it as the first one is value and the second one is the function.

So, here we go, I will explain the code below line by line:

import { useState } from "react";

const ErrorExample = () => {
  const [title, setTitle] = useState("this title is gonna be updated");

  const changeTitle = () => {
    title === "this title is gonna be updated"
      ? setTitle("useState works!")
      : setTitle("this title is gonna be updated");
  };

  return (
    <div>
      <h2>useState error example</h2>
      <h4>{title}</h4>
      <button onClick={changeTitle}>Change title</button>
    </div>
  );
};

export default ErrorExample;
Enter fullscreen mode Exit fullscreen mode

First, import { useState } from "react"; import useState from React. Assign some value to 'title' using useState and 'setTitle' is the function that we will change 'title' later const [title, setTitle] = useState("this title is gonna be updated"); In this case, initial value of 'title' is "this title is gonna be updated" (a string).

const changeTitle = () => {
    title === "this title is gonna be updated"
      ? setTitle("useState works!")
      : setTitle("this title is gonna be updated");
  };
Enter fullscreen mode Exit fullscreen mode

Code above starts with a ternary operator. It's basically the same as this:

if (title === "this title is gonna be updated") {
    setTitle("useState works!")
} else {
    setTitle("this title is gonna be updated")
}
Enter fullscreen mode Exit fullscreen mode

That means, if title is equal to "this title is gonna be updated", change its value by using setTitle function to "useState works!" (setTitle("useState works!")). Else (if title's value does not equal to "this title is gonna be updated"), then change its value back to "this title is gonna be updated" (setTitle("this title is gonna be updated")).

Final chunk of our code:

return (
    <div>
      <h2>useState error example</h2>
      <h4>{title}</h4>
      <button onClick={changeTitle}>Change title</button>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

<h4>{title}</h4> 'h4' tag receives its value from const [title, setTitle] = useState("this title is gonna be updated");. Finally, button element fires changeTitle function when it's clicked (onClick={changeTitle}).

Working With Arrays in useState Hook

Now we know a bit about useState, let's target certain data types those might be a bit confusing. Thus, I will go over arrays and objects.

First, I will share the whole code:

import { useState } from "react";

// data
const data = [
  {id: 0, name: 'Micheal'},
  {id: 1, name: 'Ahmet'},
  {id: 2, name: 'Daniel'},
]

const ContactList = () => {
  const [contacts, setContacts] = useState(data);

  const removeContacts = () => {
    setContacts([]);
  };

  const removeContact = (id) => {
    const filteredContacts = contacts.filter((contact) => contact.id !== id);
    setContacts(filteredContacts);
  };

  return (
    <div>
      {contacts.map(({ id, name }) => {
        return (
          <div style={{ display: "flex" }} key={id}>
            <h3 className="item">{name}</h3>
            <button className="btn" onClick={() => removeContact(id)}>
              Remove item
            </button>
          </div>
        );
      })}

      <button className="btn" onClick={removeContacts}>
        REMOVE ALL CONTACTS
      </button>
    </div>
  );
};

export default ContactList;
Enter fullscreen mode Exit fullscreen mode

Now, let's talk about the code in small chunks, but this time I won't be explaining each and every single line in order not to get repetitive.

const data = [
  {id: 0, name: 'Micheal'},
  {id: 1, name: 'Ahmet'},
  {id: 2, name: 'Daniel'},
]
Enter fullscreen mode Exit fullscreen mode

Above, we've got an array of objects which holds some data. Keys in those objects are id and name. Most of the time the data will be ready, and we won't have to deal with giving ids, but this is just an example

const [contacts, setContacts] = useState(data); assigned contacts's value to data array.

  const removeContacts = () => {
    setContacts([]);
  };
Enter fullscreen mode Exit fullscreen mode

I will be using removeContacts function to remove everything in the contacts array (remmeber, contacts come from data and data is an array). Well, since we re-assing a value by using setContacts([]) function, assigning an empty array will remove everything in the array. Hence, removeContacts function will remove everything from the array by converting to an empty array.

Next, rmeoveContact. As its name suggests, it's created to remove only one contact:

const removeContact = (id) => {
    const filteredContacts = contacts.filter((contact) => contact.id !== id);
    setContacts(filteredContacts);
  };
Enter fullscreen mode Exit fullscreen mode

removeContact(id) function takes a parameter - id. When 'Remove Item' button is clicked, it will bring that particular 'id' and filter (remove) it. Since, I've given contact parameter in filter method, each 'data' (we've got data array) will be represented as contact. Logic behind this code; contacts.filter((contact) => contact.id !== id), this compares if contact.id and id are not the same. Then, it returns items those have different ids.

Finally, we've got a big return, here it's:

return (
    <div>
      {contacts.map(({ id, name }) => {
        return (
          <div style={{ display: "flex" }} key={id}>
            <h3>{name}</h3>
            <button onClick={() => removeContact(id)}>
              Remove item
            </button>
          </div>
        );
      })}

      <button onClick={removeContacts}>
        REMOVE ALL CONTACTS
      </button>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

The code above maps through contacts array. Ummm... what the heck is this contacts.map(({ id, name }) I destructured what comes from contacts array right away. If you've got no clue what that is check this article from MDN Web Docs.

If I didn't destructure it, say, I did it like this contacts.map((contact) => { return () }), then when I want to refer to contact, I would've have to refer it as key={contact.id} and <h3>{contact.name}</h3>. On the other hand, because of I've destructured it, I can refer like so; key={id} and <h3>{name}</h3>. In short, I do my best to avoid dots (in my code) for some reason... personal preference.

There we go, time to talk about buttons:

<button onClick={() => removeContact(id)}>
              Remove item
 </button>
Enter fullscreen mode Exit fullscreen mode

As you can see in the code above, we've got an onClick event listener that goes for removeContact(id) function. So, this is where we get the id from. Wait, how does it get the id??? This is how contacts.map(({ id, name }). Recall, we've destructured it that way.

Finally,

<button className="btn" onClick={removeContacts}>
        REMOVE ALL CONTACTS
</button>
Enter fullscreen mode Exit fullscreen mode

Code above calls removeContact function on click. It simply re-assings our data array to an empty array.

I would go keep writing, but this post is getting too long compared to my other posts. So, in the next part I will be talking about using objects as initial values with hooks

Top comments (0)