Search code examples
reactjssetstatererender

React component doesn't re-render after setState


i have state vacations, i set it after fetch within useEffect, i have button approve that will change data in vacation state and i want to re-render component after that happens within function handleApprove , so i made up virtual state componentShouldUpdate with initial value of false and passed it as a dependency for useEffect, and when function handleApprove gets triggered, i setState to the opposite of its value !componentShouldUpdate, but the component only re-render when i click 2 times, why is that happening and why it works fine when i setState componentShouldUpdate from a child component ?


function VacationsComponent() {
  const [vacations, setVacations] = useState([{}]);
  const [componentShouldUpdate, setComponentShouldUpdate] = useState(false);

  useEffect(() => {
    const getVacations = async () => {
      const response = await fetch("http://localhost:8000/get-vacations");
      const data = await response.json();
      setVacations(data);
    };

    getVacations();
  }, [componentShouldUpdate]);

  const handleApprove = async (e, vactionId) => {
    (await e.target.value) === "approve"
      ? fetch(`http://localhost:8000/approve-vacation/${vactionId}`, {
          method: "POST",
        })
      : fetch(`http://localhost:8000/reject-vacation/${vactionId}`, {
          method: "POST",
        });

    setComponentShouldUpdate(!componentShouldUpdate);
  };

    <button onClick={(e) => handleApprove(e, item._id)}>
      APPROVE
    </button>

}


Solution

  • put the setComponentShouldUpdate(!componentShouldUpdate) inside a thenable like this, and remove the async/await construct.

    Also what was the intended purpose for setting state, I don't see the boolean being used anywhere. Usually when setting state you want the DOM to be updated somewhere, and especially with a boolean its great for toggling elements on the screen.

     const handleApprove = (e, vactionId) => {
        e.target.value === "approve"
          ? fetch(`http://localhost:8000/approve-vacation/${vactionId}`, {
              method: "POST",
            }).then(()=>{ 
               // does this go here if it is approved or when it s rejected 
               setComponentShouldUpdate(!componentShouldUpdate); 
            })
          : fetch(`http://localhost:8000/reject-vacation/${vactionId}`, {
              method: "POST",
            }).then(()=>{ setComponentShouldUpdate(!componentShouldUpdate); });
    
      
      };