Home > Mobile >  Cannot setstate in nested axios post request in react
Cannot setstate in nested axios post request in react

Time:06-06

I am trying to access the res.data.id from a nested axios.post call and assign it to 'activeId' variable. I am calling the handleSaveAll() function on a button Click event. When the button is clicked, When I console the 'res.data.Id', its returning the value properly, but when I console the 'activeId', it's returning null, which means the 'res.data.id' cannot be assigned. Does anyone have a solution? Thanks in advance

useEffect(() => {}, [activeId]);

const [activeId, setActiveId] = useState(null);

const save1 = () => {
  const handleSaveSections = async () => {
    activeMetric &&
      axios.get(api1, getDefaultHeaders()).then((res) => {
        if (res.data.length > 0) {
          Swal.fire({
            text: 'Record already exists',
            icon: 'error',
          });
          return false;
        } else {
          const data = {
            item1: item1,
            item2: item2,
          };

          axios.post(api2, data, getDefaultHeaders()).then((res) => {
            setActiveId(res.data.id);
            console.log(res.data.id); // result: e.g. 10
          });
        }
      });
  };
};

const save2 = () => {
  console.log(activeId); // result: null
};

const handleSaveAll = () => {
  save1();
  save2();
};

return (
  <button type='submit' onClick={handleSaveAll}>
    Save
  </button>
);

CodePudding user response:

Setting the state in React acts like an async function.
Meaning that the when you set the state and put a console.log right after it, like in your example, the console.log function runs before the state has actually finished updating.

Which is why we have useEffect, a built-in React hook that activates a callback when one of it's dependencies have changed.

Example:

useEffect(() => {
   console.log(activeId);
}, [activeId);

The callback will run every time the state value changes and only after it has finished changing and a render has occurred.


Edit:

Based on the discussion in the comments.

const handleSaveSections = () => {
   // ... Your logic with the `setState` at the end.
}

useEffect(() => {
   if (activeId === null) {
      return;
   }
   save2(); // ( or any other function / logic you need )
}, [activeId]);

return (
   <button onClick={handleSaveSections}>Click me!</button>
)

CodePudding user response:

As the setState is a async task, you will not see the changes directly. If you want to see the changes after the axios call, you can use the following code :

       axios.post(api2, data, getDefaultHeaders())
        .then((res) => {
         setActiveId(res.data.id)
         console.log(res.data.id) // result: e.g. 10
         setTimeout(()=>console.log(activeId),0);
      })

useEffect(() => {
}, [activeId]);

const [activeId, setActiveId] = useState(null);

const save1 = () => {
    const handleSaveSections = async () => {
        activeMetric &&
            axios.get(api1, getDefaultHeaders()).then(res => {
                if (res.data.length > 0) {
                    Swal.fire({
                        text: 'Record already exists',
                        icon: 'error',
                    });
                    return false;
                }
                else {
                    const data = {
                        item1: item1,
                        item2: item2
                    }

                    axios.post(api2, data, getDefaultHeaders())
                        .then((res) => {
                            setActiveId(res.data.id)
                            console.log(res.data.id) // result: e.g. 10
                        })
                }
            });
    }
handleSaveSections()
}

const save2 = () => {
    console.log(activeId);   //correct result would be shown here
}

const handleSaveAll = () => {
    save1();
    save2();
}
 
return (
    <button type="submit" onClick={handleSaveAll}>Save</button>
)

  • Related