skip to Main Content

There is a trend saying that devs should get rid of useEffect as much as possible in React v18.

React documentation says

An Effect lets you keep your component synchronized with some external
system (like a chat service). External system means any piece of
code that’s not controlled by React

However there are many situation where I can’t find a way to remove the useEffect without making my component stop working as expected or look extremely ugly.

I.e. the case below:

import { useEffect, useState } from "react";

interface SearchBarProps {
  programType: "movies" | "series";
}

export function SearchBar({ programType }: SearchBarProps): JSX.Element {
  const [searchTerm, setSearchTerm] = useState<string>("");
  const [selectedYear, setSelectedYear] = useState<number | null>();
  const [counter, setCounter] = useState<number>(0);

  /* 
  Restarts searchTerm and selectedYear when programType prop changes
  */
  useEffect(() => {
    searchTerm != "" && setSearchTerm("");
    typeof selectedYear == "number" && setSelectedYear(null);
  }, [programType]);

  const increase = () => {
    setCounter(counter => counter + 1);
  };

  return (
    <div className="search-bar">
      <p>{searchTerm}</p>
      <p>{selectedYear}</p>
      <span className="counter__output">{counter}</span>
      <div className="btn__container">
        <button onClick={increase}>+</button>
      </div>
    </div>
  );
}

Is there any way of removing the useEffect without affecting the component behavior?

2

Answers


  1. I updated the code, I removed the useEffect and introduced a new function called handleProgramTypeChange. This function is called whenever the programType prop changes, and it directly sets the searchTerm to an empty string and selectedYear to null. This achieves the same behavior as the previous useEffect, but without using a separate effect hook.

    import { useState } from "react";
    
    interface SearchBarProps {
      programType: "movies" | "series";
    }
    
    export function SearchBar({ programType }: SearchBarProps): JSX.Element {
      const [searchTerm, setSearchTerm] = useState<string>("");
      const [selectedYear, setSelectedYear] = useState<number | null>();
      const [counter, setCounter] = useState<number>(0);
    
      const handleProgramTypeChange = () => {
        setSearchTerm("");
        setSelectedYear(null);
      };
    
      const increase = () => {
        setCounter(counter => counter + 1);
      };
    
      return (
        <div className="search-bar">
          <p>{searchTerm}</p>
          <p>{selectedYear}</p>
          <span className="counter__output">{counter}</span>
          <div className="btn__container">
            <button onClick={increase}>+</button>
          </div>
        </div>
      );
    }
    
    
    Login or Signup to reply.
  2. Im sorry, youre right, try calling it within the useEffect, like this:

    import { useEffect, useState } from "react";
    
    interface SearchBarProps {
      programType: "movies" | "series";
    }
    
    export function SearchBar({ programType }: SearchBarProps): JSX.Element {
      const [searchTerm, setSearchTerm] = useState<string>("");
      const [selectedYear, setSelectedYear] = useState<number | null>();
      const [counter, setCounter] = useState<number>(0);
    
      const handleProgramTypeChange = () => {
        setSearchTerm("");
        setSelectedYear(null);
      };
    
      const increase = () => {
        setCounter(counter => counter + 1);
      };
    
      useEffect(() => {
        handleProgramTypeChange();
      }, [programType]);
    
      return (
        <div className="search-bar">
          <p>{searchTerm}</p>
          <p>{selectedYear}</p>
          <span className="counter__output">{counter}</span>
          <div className="btn__container">
            <button onClick={increase}>+</button>
          </div>
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search