Search code examples
javascriptreactjsuse-effect

Using useEffect like ComponentDidUpdate


I am trying to have 3 buttons where if one is in an active state, the other 2 will automatically be inactive.

 if (isActive === "true") {
            setActive2("false")
            setActive3("false")
          }
          if (isActive2 === "true") {
            setActive("false")
            setActive3("false")
          }
          if (isActive3 === "true") {
            setActive("false")
            setActive2("false")
          }

I'm aware there's probably a better way of doing this and this is a brute force option, and I'm open to your suggestions.
I have tried putting this block of code in a function and running it whenever the buttons are clicked, but that is giving me the previous state instead of the current state. So I was suggested to use the useEffect hook.

 useEffect(() => {
          
          if (isActive === "true") {
            setActive2("false")
            setActive3("false")
          }
          if (isActive2 === "true") {
            setActive("false")
            setActive3("false")
          }
          if (isActive3 === "true") {
            setActive("false")
            setActive2("false")
          }
}, [isActive, isActive2, isActive3]);

However this is giving me the same issue, where the previous state is being applied.
I am for sure doing something very wrong with this hook (i have never used it before). I have a codesandbox with all my code here


Solution

  • Have modified only the onChange handler in an efficient way without touching JSX much and have worked on your set-up only. CodeSandBox Link Checkbox-Selection

    Some Major changes that I did are as follows:

    1. Instead of setting seperate state to each button, I have used a single object with 3 keys isActive, isActive2 and isActive3.

      const [btnStatus, setBtnStatus] = useState({
       isActive: true,
        isActive2: true,
        isActive3: true
      });
      
    2. Your Handler looks something like this now.

      const addPizza = (e) => {
       setPizzaSize(e.target.name);
       setStartPrice(parseInt(e.target.value));
      const currentActive = e.target.id;
      
      if (currentActive === "isActive") {
        setBtnStatus({ isActive: true, isActive2: false, isActive3: false });
        console.log("1");
      }
      if (currentActive === "isActive2") {
        setBtnStatus({ isActive: false, isActive2: true, isActive3: false });
        console.log("2");
      }
      if (currentActive === "isActive3") {
        setBtnStatus({ isActive: false, isActive2: false, isActive3: true });
        console.log("3");
      }
      
      console.log(btnStatus);
      };
      
    3. In your JSX each button will look like this, with own ids to track the status of button.

        <button
          name="Extra Large"
          className={
            btnStatus.isActive3
              ? "button btn fourth"
              : "button btn fourthActive"
          }
          value="20"
          onClick={addPizza}
          id="isActive3"
        >
          Extra large
        </button>
      

    And here you go. All working nicely with the same code :)