score:0

that is how closures work in js. the functions passed to settimeout will get the issubmitting variable from the initial render, since issubmitting is not mutated.

you can get a function as an argument instead of prop to setissubmitting that means that issubmitting is gonna be updated value.

settimeout(() => {
  setissubmitting(issubmitting => !issubmitting);
}, 1500);

hope it will work

score:0

maybe little overkill byt you can handle this by using promise

const handlerequest = () => new promise((resolve, reject) => {
  settimeout(() => {
     createprofile(formdata, history, edit)
       .then(response => resolve(response))
       .catch(error => reject(error));
  }, 1500);
}

const onsubmit = (event) => {
  event.preventdefault();
  setissubmitting(true);

  handlerequest().finally(() => setissubmitting(false);
};

and maybe second overkill: i'm not sure why you need to submit data after 1.5s, not immediately but you can have both 1.5s loader and request sended just after submit by creating some dummy promise and using promise.all like this:

const dummypromise = () => new promise((resolve, reject) => {
  settimeout(() => resolve(), 1500);
}

const onsubmit = (event) => {
  event.preventdefault();
  setissubmitting(true);

  promise.all([
    dummmypromise(),
    createprofile(formdata, history, edit)
  ])
   .then(response => ...handle successfull response)
   .catch(error => ...handle request error)
   .finally(() => setissubmitting(false));
};

the thing is you don't know how long your request will last so by setup like this you are prepared for different situations: sumbmit request is sent immidately and promise.all will resolve after all promises resolves so if your request resolves very fast you will still have 1.5s loader, on the other hand if request will last longer than 1.5s you will still have active loader indicating that request is not finished yet. like i said overkill in your situation but i hope my comment will contain some nice inspirations how to improve handling async requests ;)

score:0

issubmitting is false by default, and upon submitting, i turn it to true, after that i set a timeout to set it back to false. but somehow, it does not get set back to false see commented code

that is how closures work

but how come in plain js, i dont have this problem? sounds like it has to do with usestate?

yes, in plain js you have the same problem. i'll show you:

let storedvalue = false;

function setstoredvalue(newvalue) {
  storedvalue = newvalue
}

// usestate() is basically this; more or less.
// the place where `storedvalue` and `setstoredvalue` are kept is differrent, 
// but that's not relevant to the issue at hand.
function gimmethevalueandasetter() {
  return [
    storedvalue,
    setstoredvalue
  ]
}

function element(label) {
  // you create a local **constant** copy of the state at this moment
  const [localvalue, setstoredvalue] = gimmethevalueandasetter();

  // and all your logs here are based off of this local **constant**!
  console.log(label, "#1 local:", localvalue, " stored:", storedvalue);

  setstoredvalue(!localvalue);

  console.log(label, "#2 local:", localvalue, " stored:", storedvalue);

  settimeout(() => {
    console.log(label, "#3 local:", localvalue, " stored:", storedvalue);

    setstoredvalue(!localvalue);

    console.log(label, "#4 local:", localvalue, " stored:", storedvalue);
  }, 100);
}

// render element
element("first render");
console.log("after first render:", storedvalue);
element("second render");
.as-console-wrapper{top:0;max-height:100%!important}

back to your code. instead of flipping the state, better set the explicit value. this is also simpler to reason about:

const onsubmit = (e) => {
  e.preventdefault();

  // we don't want to submit while another submit is still in progress
  // right?
  if(issubmitting) return; 

  setissubmitting(true);
  settimeout(() => {
    createprofile(formdata, history, edit);
    setissubmitting(false);
  }, 1500);
};

ain't this simpler to reason about than what you had before? issubmitting was false then i've flipped it to true, so now i have to flip it again to get back to false, ...

score:1

the state update using the updater provided by usestate hook is asynchronous, and will not immediately reflect the updated changes.

i.e

console.log(issubmitting); // false
setissubmitting(!issubmitting);
console.log(issubmitting); // false

instead you should useeffect,

const onsubmit = (e) => {
    e.preventdefault();
    setissubmitting(!issubmitting);
  };

useeffect(() => {
    // action on update of issubmitting
  if(issubmitting) {
    settimeout(() => {
      createprofile(formdata, history, edit);
      setissubmitting(!issubmitting);
    }, 1500);
  }
}, [issubmitting]);

Related Query

More Query from same tag