React.js Why Hooks

Why Hooks?: Hooks are functions that let us “hook into” state and lifecycle functionality in function components.

Hooks allow us to:

  • reuse stateful logic between components

  • simplify and organize our code to separate concerns, rather allowing unrelated data to get tangled up together

  • avoid confusion around the behavior of the this keyword

  • avoid class constructors, binding methods, and related advanced JavaScript techniques

Rules for Using Hooks

There are two main rules to keep in mind when using hooks:

  1. Only call hooks from React function components.

  2. Only call hooks at the top level, to be sure that hooks are called in the same order each time a component renders.

Common mistakes to avoid are calling hooks inside of loops, conditions, or nested functions.


useEffect(() => {

if (userName !== '') {

  localStorage.setItem('savedUserName', userName);

}

});

Side Effects

The primary purpose of a React component is to return some JSX to be rendered. Often, it is helpful for a component to execute some code that performs side effects in addition to rendering JSX.

In class components, side effects are managed with lifecycle methods. In function components, we manage side effects with the Effect Hook. Some common side effects include: fetching data from a server, subscribing to a data stream, logging values to the console, interval timers, and directly interacting with the DOM.

The Effect Hook

The useEffect hook performs side effects every time a component renders. useEffect accepts two arguments in the form of useEffect(callback, dependencies). The callback argument holds the side-effect logic and is executed every time a render happens.

import React, { useState, useEffect } from 'react';

function TitleCount() {

 const [count, setCount] = useState(0);

  useEffect(() => {

   document.title = `You clicked ${count} times`;

 }, [count]);

  return <button onClick={(prev) => setCount(prev + 1)}>+</button>;

}

Effect Cleanup Functions

The cleanup function is optionally returned by the first argument of the Effect Hook.

If the effect does anything that needs to be cleaned up to prevent memory leaks, then the effect returns a cleanup function. The Effect Hook will call this cleanup function before calling the effect again as well as when the component is being removed from the DOM.

useEffect(() => {

 document.addEventListener('keydown', handleKeydown);

 //Clean up the effect:

 return () => document.removeEventListener('keydown', handleKeydown);

});

Multiple Effect Hooks

useEffect() may be called more than once in a component. This gives us the freedom to individually configure our dependency arrays, separate concerns, and organize the code.


function App(props) {

const [title, setTitle] = useState('');

useEffect(() => {

  document.title = title;

}, [title]);

const [time, setTime] = useState(0);

useEffect(() => {

  const intervalId = setInterval(() => setTime((prev) => prev + 1), 1000);

  return () => clearInterval(intervalId);

}, []);

 // ...

}

Effect Dependency Array

The dependency array is used to tell the useEffect() method when to call the effect.

  • By default, with no dependency array provided, the effect is called after every render.

  • An empty dependency array signals that the effect never needs to be re-run.

  • A non-empty dependency array signals that the hook runs the effect only when any of the dependency array values changes.

useEffect(() => {

alert('called after every render');

});

useEffect(() => {

alert('called after first render');

}, []);

useEffect(() => {

alert('called when value of `endpoint` or `id` changes');

}, [endpoint, id]);

The State Hook

The useState() Hook lets you add React state to function components. It should be called at the top level of a React function definition to manage its state.

initialState is an optional value that can be used to set the value of currentState for the first render. The stateSetter function is used to update the value of currentState and rerender our component with the next state value.

const [currentState, stateSetter] = useState(initialState);

State Setter Callback Function

When the previous state value is used to calculate the next state value, pass a function to the state setter. This function accepts the previous value as an argument and returns an updated value.

If the previous state is not used to compute the next state, just pass the next state value as the argument for the state setter.

function Counter({ initialCount }) {

const [count, setCount] = useState(initialCount);

return (

  <div>

    Count: {count}

    <button onClick={() => setCount(initialCount)}>Reset</button>

    <button onClick={() => setCount((prevCount) => prevCount - 1)}>-</button>

    <button onClick={() => setCount((prevCount) => prevCount + 1)}>+</button>

  </div>

);

}

Multiple State Hooks

useState() may be called more than once in a component. This gives us the freedom to separate concerns, simplify our state setter logic, and organize our code in whatever way makes the most sense to us!

function App() {

const [sport, setSport] = useState('basketball');

const [points, setPoints] = useState(31);

const [hobbies, setHobbies] = useState([]);

}



—--------------------------------Exercise

The Effect Hook tells our component to do something every time it’s rendered (or re-rendered). Combined with states, we can use the Effect Hook to create interesting dynamic changes in our web pages!

Suppose we want to allow a user to change the title of the web page tab every time they type. We can implement this with the Effect Hook (useEffect()

import React, { useState, useEffect } from 'react';


function PageTitle() {

  const [name, setName] = useState('');


  useEffect(() => {

    document.title = `Hi, ${name}`;

  });


  return (

    <div>

      <p>Use the input field below to rename this page!</p>

      <input onChange={({target}) => setName(target.value)} value={name} type='text' />

    </div>

  );

}-----------------------

  1. First, we import the Effect Hook from the 'react' library:

import { useEffect } from 'react';

  1. The useEffect() function has no return value as the Effect Hook is used to call another function. We pass the callback function, or effect, to run after a component renders as the argument of the useEffect() function. In our example, the following effect runs after each time the PageTitle component renders:

() => { document.title = `Hi, ${name}`;}

Here, we assign Hi, ${name} as the value of document.title.

  1. The onChange event listener triggers the PageTitle component to be re-rendered every time the user types in the input. Consequently, this triggers useEffect() and changes the document’s title.

  2. Notice how we use the current state inside of our effect. Even though our effect is called after the component renders, we still have access to the variables in the scope of our function component! When React renders our component, it will update the DOM as usual, and then run our effect after the DOM has been updated. This happens for every render, including the first and last one.

Practice:

  1. Import the Effect Hook, the State Hook, and React from the 'react' library.

Make sure to import everything in one line.

import React, { useState, useEffect } from 'react';


  1. Call useEffect() with a callback function that creates an alert with the current value of count.

Start clicking the button to see when our alert() function is called and be sure that it is logging the values that we’d expect!

NOTE: You do not need to call setCount() to complete this step — setCount() is already used within the handleClick() callback.

const [count, setCount] = useState(0);

useEffect(() => {

 alert('Count: ${count}');

});


  1. Use a template literal so that the message in our alert dialog reads: “Count: 0”, then “Count: 1”, then “Count: 2”, etc.

useEffect(() => {

 alert(`Count: ${count}`);

});

—----------------------------


Comments

Popular posts from this blog

React Full Stack Project Design Build Launch

React useState Hook – Complete Guide

Building an AI-Powered App with Next.js, Tailwind CSS, and OpenAI API