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 ifbranchName
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]);