Home > front end >  useEffect call the function after the state is updated
useEffect call the function after the state is updated

Time:02-17

I have the useEffect function

useEffect(() => {
  let branchName = getBranchName();
  setBranchName(branchName);
  refreshBranchStatus()
}, []);

I want to call the refreshBranchStatus()function once, after setting the state of branchName

I tried write await before setBranchName(branchName); but it didn't work.
I tried write a second function

  useEffect(async () => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
      await refreshBranchStatus();
    }
  }, [branchName]);

but it is called even when branchName has not changed(after page load, not after setBranchName(branchName);)

How can I get the correct behavior?
thanks in advance

CodePudding user response:

A key question to first ask yourself is:

Should refreshBranchStatus be re-invoked if branchName changes?

If it depends on the value of branchName then in the majority of cases, yes, it probably should be re-invoked. But a comment thread on this answer seems to be implying that this is an obscure case where it depends on the value but shouldn't be re-invoked if that value changes.

Based on the answer to the above, there are two approaches:


Option 1: Re-invoke when state changes

Create a second effect. The first is triggered only once when the component is first loaded:

useEffect(() => {
  let newBranchName = getBranchName();
  setBranchName(newBranchName);
}, []);

The other is triggered when the branchName state value changes:

useEffect(() => {
  refreshBranchStatus();
}, [branchName]);

Note: This should also run on the initial load because the branchName state value "changed" (or "was set to") its initial state. So I'd expect this effect to be executed twice. Once on the initial state of branchName and once on the updated state of branchName. (And again on any subsequent updates of that state.)


Option 2: Remove the dependency on state

If you truly only want to invoke refreshBranchStatus once, and only once, when the component first loads and it needs the value of branchName to execute then you should pass that value to the function. Something like this:

useEffect(() => {
  let newBranchName = getBranchName();
  setBranchName(newBranchName);
  refreshBranchStatus(newBranchName);
}, []);

In this scenario refreshBranchStatus isn't internally checking the branchName state but is more of a "pure" function which requires that it be provided with the value it needs. Since you have that value when you invoke the function, just pass it to the function.

CodePudding user response:

Every usEffect will be called on the initial render of the component, so if you're waiting for a value to be set, you need to check for it in the effect body.

I think what you're asking for could be achieved like this:

useEffect(() => {
  let branchName = getBranchName();
  setBranchName(branchName);
}, []);

useEffect(() => {
  if (branchName) refreshBranchStatus();
}, [branchName]);
  • Related