luisanton-io / recoil-nexus

MIT License
163 stars 13 forks source link

Latest state is present in a useEffect but not when calling getRecoil from an async function #19

Closed jennmueng closed 2 years ago

jennmueng commented 2 years ago

I have a component that calls an async function inside a useEffect which has a dependency on a string value inside a Recoil atom state. Inside the useEffect the value locationName is the latest value, while in the async function call that immediately calls getRecoil returns the old value (that defaults to the empty string ""). Calling getRecoil again inside a setTimeout returns the new value however.

// In a component
const { locationName } = useRecoilValue(searchAreaState);
const { topPicks, isLoadingTopPicks } = useRecoilValue(searchState);

React.useEffect(() => {
    if (locationName !== '') {
      console.log('locationName: ', locationName);
      getTopPicks().catch(handleErrorCatch);
    }
}, [locationName, getTopPicks]);
// Async function outside component
export const getTopPicks = async (): Promise<void> => {
  setTimeout(() => {
    console.log('Inside setTimeout: ', getRecoil(searchAreaState).locationName);
  }, 10);

  console.log('Inside async function: ', getRecoil(searchAreaState).locationName)
  // ...
};

The logs:

[Wed Feb 09 2022 15:10:40.534]  LOG      locationName: Orlando, Florida
[Wed Feb 09 2022 15:10:40.539]  LOG      Inside async function:  
[Wed Feb 09 2022 15:10:40.701]  LOG      Inside setTimeout:  Orlando, Florida

For now I'll be passing through the locationName as an argument to the getTopPicks function but does anyone have any insight on why this bug happens?

luisanton-io commented 2 years ago

Hi, I had some time and I tried to reproduce this, without much luck. To answer your concern I would appreciate if you could help me replicate the unexpected behavior, this is what I tried: CodeSandbox

burgalon commented 2 years ago

i'm encountering this too....

jennmueng commented 2 years ago

I'm often encountering issues where the recoil state is not updated synchronously after a setRecoil as well.

Wish I could provide a reproducible example but have yet to have the time to look into creating one. The app is a pretty large closed source React Native application. I wonder if either the fact that the component tree is gigantic or the library is running on React Native has any effect on this issue.

jennmueng commented 2 years ago

@burgalon @luisanton-io I found a fix and pushed it to #22, sorry that I'm still unable to provide a reproducible but this fix was what worked for our app.

luisanton-io commented 2 years ago

Thanks @jennmueng ! Published in 0.3.16. Closing for now.