DEV Community

Cover image for useEffect() vs useState(), props vs callback, Dependency types for useEffect
Daniel
Daniel

Posted on

useEffect() vs useState(), props vs callback, Dependency types for useEffect

useEffect() vs useState()

useState is a React hook used to manage and update state within a functional component. It's a way to store data that can change over time and cause re-renders based on any changes. It also allows you to declare and update a piece of local state within a component. This can be useful for when you need to keep track of data that may change over time and want to trigger a re-render when the state changes.

As a simple example, here is a counter using useState:

import React, { useState } from 'react';

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

  const increment = () => setCount(count + 1);

  return (
    <div>
    <p>Count: {count}</p>
    <button onClick={increment}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Other use cases include managing input values, toggling UI elements, or storing and updating data specific to a component.

useEffect is another React hook used to perform side effects in a functional component. Side effects include data fetching, DOM manipulation, setting up subscriptions, and more. It allows you to run code after the initial render and in response to changes in state or props.

Here is an example:

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

function App() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetchApi()
  }, []); // Empty dependency array means this effect runs once after the initial render

  const fetchAPI = () => {
  // Fetch data from an API
    fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => setData(data));
   }

  return (
    <div>
    {data ? <p>Data: {data}</p> : <p>Loading...</p>}
    </div>
  );

}
Enter fullscreen mode Exit fullscreen mode

UseEffect is useful for when you need to interact with the outside world, handle asynchronous operations, or perform cleanup tasks when the component is unmounted.

useState is used to manage component-specific state, while useEffect is used to handle side effects or actions that are not directly related to component state but need to be triggered based on changes in state or props. These two hooks are essential components to build React projects with.

props vs Callbacks

Props (short for properties) are used to pass data from a parent component to a child component. Props are read-only; the child component cannot modify its props directly. They are intended for communication and data transfer between components. Props are defined when you render a component and are passed as attributes in JSX elements.The parent component then sets and updates the props of its child components.

In our PlayerCard.js for example, 'player' is an example of a prop, which is passed down from PayerList.js:

import React from 'react';

const PlayerItem = ({ player}) => {
  const offensiveRating = ((player.PTS / player.minutes_played) * 100).toFixed(2);
  const defensiveRating = (player.BLK * 0.6 + player.STL * 0.4).toFixed(2);

  return (
    <div className="card">
    <div className="card-content">
        <h2>{player.player_name}</h2>
        <img src={player.image} alt={player.player_name} className="player-avatar" />
        <p>Points: {player.PTS}</p>
        <p>Offensive Rating: {offensiveRating}</p>
        <p>Defensive Rating: {defensiveRating}</p>
        <p>Assists: {player.AST}</p>
    </div>

    </div>
  );
};

export default PlayerItem;

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

// send props from App.js 
const PlayerList = ({players, isDarkMode, toggleDarkMode, handleAddNewPlayer}) => {

  return (
    <div className={isDarkMode ? 'dark-mode' : 'light-mode'}>
      <nav>
        <button onClick={toggleDarkMode}>
          {isDarkMode ? 'Light' : 'Dark'} Mode
        </button>
      </nav>

      <div>
        {players.map((player) => (
          <PlayerCard key={player.id} player={player} />
        ))}
      </div>
    </div>
  );
};

export default PlayerList;
Enter fullscreen mode Exit fullscreen mode

Playerlist loops through a map of props 'players' which is passed down from App.js:

 <PlayerList
   players={players}
   toggleDarkMode={toggleDarkMode}
   isDarkMode={isDarkMode}
 />
Enter fullscreen mode Exit fullscreen mode

Callbacks, on the other hand, involves passing functions as props to child components. This allows the child component to trigger functions defined in the parent component, enabling communication and actions to be initiated in the parent component based on events or user interactions in the child component.

From our App.js, we have toggleDarkMode which is an example of a callback function:


  const toggleDarkMode = () => {
    setIsDarkMode((prevIsDarkMode) => !prevIsDarkMode);
  };
return (
    <Router>
      <div>
         ...
       <Route
          path="/"
          element={
            <PlayerList
              players={players}
              toggleDarkMode={toggleDarkMode}
              isDarkMode={isDarkMode}
            />
          }
        />
     </div>
   ...
Enter fullscreen mode Exit fullscreen mode

We can also access toggleDarkMode from PlayerList.js

const PlayerList = ({players, isDarkMode, toggleDarkMode, handleAddNewPlayer}) => {

  return (
    <div className={isDarkMode ? 'dark-mode' : 'light-mode'}>
      <nav>
        <button onClick={toggleDarkMode}>
          {isDarkMode ? 'Light' : 'Dark'} Mode
        </button>
      </nav>
Enter fullscreen mode Exit fullscreen mode

Depenedency Types for useEffect()

The useEffect hook in React accepts an optional second argument, which is an array of dependencies. The dependency array controls when the effect should run. There are three primary types of dependencies:

  1. Empty Dependency Array ([]): When the dependency array is empty, as in useEffect(() => {...}, []), the effect runs only once, similar to componentDidMount in class components. It doesn't re-run when any props or state variables change. This is usually done to fetch data from API when the component mounts.

  2. Specific Props or State Dependencies: You can specify one or more props or state variables in the dependency array, such as [players]. The effect will run whenever the values of those dependencies change. Here when 'players' state changes, it re-renders.

useEffect(() => {
  // ... (code)
}, [players]);
Enter fullscreen mode Exit fullscreen mode

Callbacks as Dependencies: You can also include callback functions in the dependency array. The effect will run whenever those callbacks change, which can be useful for handling side effects based on callback changes.

useEffect(() => {
  // ... (code)
}, [someCallback]);
Enter fullscreen mode Exit fullscreen mode

Above, we have described the use cases for useState() and useEffect(), what the differences between props and callbacks are, as well as to describe the three scenarios for dependency types for useEffect(). Hope you enjoyed the read and find this useful for tackling projects using useState, useEffect, props, and callbacks.

Top comments (0)