-
Notifications
You must be signed in to change notification settings - Fork 114
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
Multiple re-renders on _layouts and pages. #320
Comments
+1 getting this as well. My JS thread goes down to ~30 frames each on the perf monitor each time a new tab screen is clicked. It's pretty unusable compared to the previous version. So I had to remove expo router, sucks cause it was ~3 days of work for me (complex app). Might try again at a later version when it's more stable. |
Hey folks, any news here? My app rely on useEffect to kick of a video streaming and because of that, it is starting the streaming twice leading to some weird behaviour. Any update could help me, even if it is to say that this will not be tackle right now. I really want to push expo router forward in my app since I am totally into it's benefits. |
I am investigating this deeply and found this old thread that I suspect is related. |
Yeah also facing the same problem.... anyone got a workaround on that issue? Same as @TowhidKashem. Put a lot of effort in designing the layout. Need to switch because of performance and data fetching issues. |
|
Feel free to ask me anything @marklawlor. |
@marklawlor any updates here? just a friendly reach out so I can plan accordingly. |
Its not a simple fix, but I'm working on something. If this issue is causing you problems, you can use API's like |
@marklawlor thank you for your answer. Maybe as part of a impostor syndrome, I was still think that the issue could be only on my code base and some mistake I made. So your confirmation helped me. I am already doing react memoization as part of a good practice but thanks for pointing this route (no pun intended). |
Can someone explain why you need I thought the point of:
would mean that the entry route is /welcome and not /? |
Unfortunately, I have three simple screens, using only a In a large application, the performance will be very poor. |
Hi @marklawlor ! Firstly, thanks for looking into the issue and trying to fix it. |
Also though I was going crazy when every screen in the stack is re-rendering after the user navigates to a new screen. This led to a strange behavior where every previous screens that re-rendered are still trying to read the search params that may no longer be passed on to the newer screens. |
I have 2-3 ways to fix that issue if anyone is still having this issue. |
I'm still having this issue, can you share your fixes regarding this issue? |
If you are experiencing this issue you can also the |
The easiest way to fix this would be just change the folder name of you are most likely using a Stack at the root that has the Tabs inside it that looks like this:
You can change it to this:
the only issue with this one is now Another way would be to have one big Tabs in the root like this in the
add The main cause of this multiple render bug is when you navigate form a root Stack screen to a screen that uses group syntax Hope that helps. |
@marklawlor are you expecting this to be fixed with v2? Are there related issues/PRs to follow? |
Having this issue when using screens with a _layout file. When the l remove the _layout file, no more double useEffect calls. |
This seems to be fixed on the Edit: Scratch that, same issue if I use a Redirect. |
Using latest expo-router (beta-10) and expo beta 4. The issue persists. Having 2-3 mounts. The structure is very similar as in the described issue. Seems escalaty to mee! :) |
I'm also experiencing a bunch of unnecessary rerenders every time a screen loads. Spent a bunch of time moving over from reactnav, shame to need to undo it... |
same issue on sdk 49 stable |
Worth clarifying that this doesn't happen on all layout routes, can be triggered by a number of reasonable causes like using |
If anyone’s willing to provide me with a minimal repo for reproduction, I’m happy to look into and try fix this issue. Edit: seems like this person has a similar issue and has a repo I can look at #838 |
There appear to be some unrelated issues linked in here. I'll assume #838 is an accurate representation of this issue as it has a reproducible demo linked which generally aligns with the comments I'm reading in here. When it's fixed in expo/expo#24147, I'll close this issue. If people have further issues afterwards, please open new issues with reproducible demos. |
# Why Prevent double renders by cloning state to avoid leaking state between functions. - fix expo/router#838 - fix expo/router#733 - fix expo/router#320 - The issue expo/router#320 has multiple different things linked, but the original case appears to be fixed. - possibly also addresses expo/router#847 <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> # How - Prevent mutating the input state to avoid invalidating the nested state. # Test Plan - The testing library doesn't seem to support this case. @marklawlor has been tasked with ensuring the original branch can detect the error https://github.com/expo/expo/compare/%40evanbacon/router/fix-838 Just in case the testing library isn't fixed, I ran locally with: - `app/_layout.js`, `app/(a)/_layout.js`, `app/b/_layout.js` ```js import { Slot } from "expo-router"; export default function RootLayout() { return <Slot /> } ``` - `app/(a)/index.js` ```js import { router, useNavigation } from "expo-router"; import { View } from "react-native"; export default function App() { // const navigation = useNavigation(); setTimeout(() => { router.push("/b"); // navigation.push("b"); }); return ( <View /> ); } ``` - `app/b/index.js` ```js import { usePathname } from 'expo-router'; import { Text, View } from 'react-native'; let i = 0; export default function Page() { const path = usePathname(); i++; return ( <View style={{ flex: 1, backgroundColor: i > 1 ? "red" : "white" }}> <Text>Path: {path}</Text> </View> ); } ``` <!-- Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction. --> # Checklist <!-- Please check the appropriate items below if they apply to your diff. This is required for changes to Expo modules. --> - [ ] Documentation is up to date to reflect these changes (eg: https://docs.expo.dev and README.md). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). --------- Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
A fix has been published in |
Can confirm that the new fix on expo-router version 2.0.4 solves the issue. |
What if I can't upgrade to v 2? I have some other sdk 49 bugs that limiting my base from upgrade to sdk 49 currently. |
@idrakimuhamad Can't say for sure. As it seems the bug exists on earlier versions of expo-router. So you might have to look for another work around in terms of upgrading to the latest expo sdk. |
@idrakimuhamad you can try pulling this patch into your local copy of expo-router 7b6032d and running |
Sweet. Thanks! |
i don't know if it's a good solution. i used useEffect in the _layout.js and now it runs once. import { Stack } from "expo-router";
import { Text } from "react-native";
import React, { useEffect, useState } from "react";
export default function Layout() {
const [loading, setLoading] = useState('true')
useEffect(()=>{
setLoading(false);
},[]);
if(loading){
return <Text>Loading...</Text>
}else{
return <Stack name="home" screenOptions={{ headerShown : false}} />;
}
} |
Thanks! I updated to |
This bug has re-emerged in 3.4.6. |
It stills happens when I "minimize" the app and open it again. My "home" page re-render as much as I do this. I'm using 3.4.5 expo router version. |
In some part of my app I replaced the |
I too am having the same issue as of March 2024. The frames do not properly mount on time, so each item in the stack for me must be wrapped by a useeffect, causing multiple renders. |
This repo (and v2) is in maintenance mode and will only receive updates for critical issues. If you are experience this issue on v3, please create a new issue with a full reproduction on the https://github.com/expo/expo repo |
Gotcha, thanks @marklawlor! |
If someone finds this thread, maybe this will help. I was having re-render issues on SDK 50 and using v3. Then fixed by Replacing buttons that had |
Happening on SDK 50 and v3.4.8 |
I keep reproducing the issue with Expo SDK 50.0.13 and Expo Router 3.4.8 when using useLocalSearchParams() on Android compilation … |
For better visibility and tracking, and since this seems to be a new iteration of a once-fixed issue, I re-opened a new issue with a new, minimal reproducable example: expo/expo#29163 Edit 1: as @lukaskf points out, this might be an issue with |
This worked for me! The imperative way of routing in expo-router is very powerful but may cause unwanted behavior if you don't fully understand it. My main issue was using I think it's because the Here are the docs that explains this: https://docs.expo.dev/router/navigating-pages/ Also, using |
use router.navigate() or |
For anyone else hitting this, in my situation it turned out that my pages were setup like this:
Removing the <Stack.Screen> (so the content only contains |
# Why Prevent double renders by cloning state to avoid leaking state between functions. - fix expo/router#838 - fix expo/router#733 - fix expo/router#320 - The issue expo/router#320 has multiple different things linked, but the original case appears to be fixed. - possibly also addresses expo/router#847 <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> # How - Prevent mutating the input state to avoid invalidating the nested state. # Test Plan - The testing library doesn't seem to support this case. @marklawlor has been tasked with ensuring the original branch can detect the error https://github.com/expo/expo/compare/%40evanbacon/router/fix-838 Just in case the testing library isn't fixed, I ran locally with: - `app/_layout.js`, `app/(a)/_layout.js`, `app/b/_layout.js` ```js import { Slot } from "expo-router"; export default function RootLayout() { return <Slot /> } ``` - `app/(a)/index.js` ```js import { router, useNavigation } from "expo-router"; import { View } from "react-native"; export default function App() { // const navigation = useNavigation(); setTimeout(() => { router.push("/b"); // navigation.push("b"); }); return ( <View /> ); } ``` - `app/b/index.js` ```js import { usePathname } from 'expo-router'; import { Text, View } from 'react-native'; let i = 0; export default function Page() { const path = usePathname(); i++; return ( <View style={{ flex: 1, backgroundColor: i > 1 ? "red" : "white" }}> <Text>Path: {path}</Text> </View> ); } ``` <!-- Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction. --> # Checklist <!-- Please check the appropriate items below if they apply to your diff. This is required for changes to Expo modules. --> - [ ] Documentation is up to date to reflect these changes (eg: https://docs.expo.dev and README.md). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). --------- Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
Summary
Main Issue
I noticed that my screen is triggering the initial useEffect twice. I was suspecting that some upper level component was unmounting and mounting again, but turns out that the _layout.tsx file is rendering more than once.
Details
My currently structure is the following:
Logs
When I reload my app and the router put me at the logged index, these were the renders that happened:
Why app/(app)/_layout.tsx rendered 3 times and app/(app)/home/ndex.tsx rendered twice?
I understand that the first render of the layout is related to the (app)/index that does the redirect. Another is related to the screen I was redirected to. But what about the third time? I also noticed that it is not being remounted because does not trigger the unmount of the useEffect.
Minimal reproducible example
My app/(app)/_layout.tsx for reference:
The text was updated successfully, but these errors were encountered: