Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useStoreState doesn't react to changes in the state after Fast Refresh in React Native #477

Closed
sansiaali opened this issue Apr 17, 2020 · 12 comments

Comments

@sansiaali
Copy link

Hi,

I added easy-peasy(v.3.3.0) successfully into a new React Native(v0.62.2) project but noticed that a function component using useStoreState will not react to the state after editing the component code. My button will send a request, receive a new picture of a dog and set that dog into the state but my component will not detect the state change. I have React Native's Fast Reload enabled.

Here is my test component (TestComponent.tsx):

import ...

export function TestComponent() {
  const dog = useStoreState((state) => state.test.dog);
  const getDog = useStoreActions((actions) => actions.test.getDog);

  const handleGetDogPress = useCallback(async () => {
    try {
      await getDog();
    } catch {
      console.log('Simulated api error occurred');
    }
  }, [getDog]);

  return (
    <View style={styles.container}>
      {dog && <Image style={styles.logo} source={{uri: dog}} />}
      <Button title="Get Dog" onPress={handleGetDogPress} />
    </View>
  );
}

const styles = StyleSheet.create(...)

Fast Refresh documentation points out that it'll try to preserve the state if a change is done to a file that only exports a React component:

When possible, Fast Refresh attempts to preserve the state of your component between edits. In particular, useState and useRef preserve their previous values as long as you don't change their arguments or the order of the Hook calls.

If I change the order of the useStoreState and useStoreActions, the useStoreState hook will work until I make a modification that makes Fast Refresh try to preserve values of useStates and useRefs. Putting // @refresh reset somewhere in the file also works but it forces the component to re-render on every save. Disabling Fast Refresh works as well but it makes the developer experience really bad.

Maybe the bug is related to the useRef hooks used in the useStoreState? I checked the code but I'm afraid I don't know enough about hooks/redux/easy-peasy yet to fix it myself.

Is there anyone that can look into this?

@ctrlplusb
Copy link
Owner

Hi @shancial

Thanks for this report. I can empathise with that pain. I'll def make some time to look into this for you.

@sansiaali
Copy link
Author

Thanks!

I can provide you with the test project code that I tested this with, but I basically used the official guide (npx react-native init AwesomeTSProject --template react-native-template-typescript) to set up a base and added easy-peasy with a property, setter and a thunk.

@Nr9
Copy link

Nr9 commented May 5, 2020

same issue.

@sansiaali
Copy link
Author

sansiaali commented May 5, 2020

It seems like Fast Refresh / react-refresh is also coming to create-react-app in the future.

@DaneEveritt
Copy link

Can also confirm this is happening to me as well. Anything I can do that would help with getting this looked into? :)

@ctrlplusb
Copy link
Owner

Hi all, I want to look into this. Are you all running the Expo CLI, and RN Web?

@DaneEveritt
Copy link

I am using the standard react-native CLI and React Native.

@rfermann
Copy link

Are you all running the Expo CLI, and RN Web?

Next.js and CRA. Both are also facing this issue. You can find a small reproduction repo based on CRA here.

It's stripped down to only containing a counter and a button for incrementing the counter.

Changing the component makes the counter stop updating when clicking the button. According to the Redux DevTools the store state keeps updating on click.
Changing the component again without refreshing the page updates the counter once to the current store value, but the counter still does not update when clicking the button.

Changing the store logic (like changing the incrementing value) makes the refresh break completely. No changes on the component are reflected on the website anymore. Instead the counter keeps updating on every click, unfortunately it updates based on the old incrementing value.
I am not sure if that is the same issue or a different one, though.

@hutber
Copy link

hutber commented Nov 1, 2020

I confirm the same as @rfermann issue is happening with nextjs.

@mrapczynski
Copy link

mrapczynski commented Dec 2, 2020

I just ran into this too building an app that uses Fast Refresh, but for the web, and not with React Native.

Edit: After an HMR update, the actions are definitely continue to fire based on adding console.debug statements to the function.

It seems like the type of state update may be involved. If I push onto an array even after a hot update, the state continues to update fine and components on screen will refresh as expected. However, if I modify the array with a splice to delete an item, then the components do not refresh (yet the change is applied to the state because I am using localStorage persistence).

Edit 2: I also see that performing an behavior (i.e. button click) which modifies local state with a useState() hook causes all components to refresh once (including those using state from EP), but the action handlers that delete an item with a .splice() continue to not trigger a refresh. Very odd.

@jmyrland
Copy link
Collaborator

We're also starting to see the issue of fast refresh not working properly with easy-peasy. I've reproduced the issue in this codesandbox:

chrome_NVK65pZfLX

Any ideas as to what is causing this @ctrlplusb ?

@ctrlplusb
Copy link
Owner

Fixed in v5.1.0 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

8 participants