What are useState, useEffect and useRef hooks?
Published: 2024-03-29 23:47:42

In this post, I'd like to touch on some of the commonly used React hooks. React hooks are first introduced in React 16.8. They allow functional components to use state, side effects, and create references to DOM elements respectively. They let you use state and other React features without writing a class.

## useState 
`const [count, setCount] = useState(0)`

- `useState` is a hook that allows functional components to manage state within the component.
- When you call useState, it returns an array with two elements: the current state value and a function that lets you update it. (i.e. `[count, setCount]`)
- The initial state is passed as an argument to useState. (i.e. `useState(0)`)

**Applying the `useState` hook**
I like to use the useState hook to manipulate button states.

```
const [buttonText, setButtonText] = useState("Add To Cart");
const [buttonDisabled, setButtonDisabled] = useState(false);

const handleClick = () => {
    setButtonText("Added to Cart!");
    setButtonDisabled(true);
  };

<Button variant="primary"
        disabled={buttonDisabled}
        onClick={handleClick}>
        {buttonText}
</Button>
```

What this code does:
It creates a button component that starts enabled with the text "Add To Cart". When clicked, the text changes to "Added to Cart!" and the button becomes disabled.

Explanation:
1. The initial value of buttonText is set to "Add To Cart", and the initial value of buttonDisabled is set to a Boolean value.
2. The useState hook returns an array with two elements: the current state value and a function to update that value.
3. The `handleClick` function will be called when the button is clicked. Inside this function, setButtonText is called with the argument "Added to Cart!" to update the button text, and setButtonDisabled is called with true to disable the button.

## useEffect
```
useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Only re-run the effect if count changes
```

- `useEffect` is a hook that allows functional components to perform side effects (such as data fetching, subscriptions, or manually changing the DOM) after the component renders.
- It takes a function as its first argument, which contains the code for the side effect.
- By default, useEffect runs after every render, including the initial render.
- You can specify dependencies as the second argument to control when the effect is re-run.

**Applying the `useEffect` hook**
This hook is commonly utilised for fetching data.

```
const [wishlistItems, setWishlistItems] = useState([]);

useEffect(() => {
    fetch("http://localhost:4000/wishlist")
      .then((response) => response.json())
      .then((json) => {
        setWishlistItems(json);
      });
  }, []);
```

What this code does:
It fetches wishlist items from a server when the component mounts and updates the component's state with the fetched data.

Explanation:
1. `useEffect` is like a special function in React that runs some code when something in the component changes.
2. In this example, it initiates a fetch request to the specified URL and fetches data from the server.
3. Next, it chains a 'then' method to the fetch call to parse the response body as JSON. This converts the response from the server into a JavaScript object.
4. It then chains another 'then' method to handle the parsed JSON data. Here, it updates the 'wishlistItems' state with the fetched JSON data.
5. Finally, the hook is configured with an empty dependency array [], which ensures that the effect runs only once after the component mounts.


## useRef
`const target = useRef(null);`

- The `useRef` Hook allows you to reference a value that’s not needed for rendering.
- It can be used to store a mutable value that does not cause a re-render when updated.
- It can be used to access a DOM element directly.

**Applying the `useRef` hook**
In my project, I used the `useRef` hook to create a reference to a DOM element (the button) so that it can be accessed and used elsewhere in the component, such as positioning an overlay relative to the button.

```
const [show, setShow] = useState(false);
const target = useRef(null);

const handleAddToWishlistBtn = () => {
    setShow(true);

    setTimeout(() => {
      setShow(false);
    }, 2000);

  };

<Button
          variant="danger"
          ref={target}
          onClick={handleAddToWishlistBtn}
        >
          Add to Wishlist
</Button>
        <Overlay target={target.current} show={show} placement="right">
          {(props) => (
            <Tooltip id="overlay-example" {...props}>
              Added to Wishlist!
            </Tooltip>
          )}
        </Overlay>
```

What this code does:
When the "Add to Wishlist" button is clicked, an overlay tooltip appears next to it, displaying the message "Added to Wishlist!". The tooltip disappears after 2 seconds. The positioning of the tooltip is determined by the button element.

Explanation:
1. `const target = useRef(null)` here is used to reference my button element without causing unnecessary re-renders when the ref's value is updated.
2. The `target.current` reference is then passed as the target prop to the <Overlay> component. This allows the overlay to position itself relative to the button element.
3. As such, when the <Overlay> component is triggered to appear or disappear, it doesn't cause the entire page to re-render. Instead, React only updates the parts of the DOM that have changed, which in this case would be the rendering of the overlay itself.