expo / router

[ARCHIVE]: Expo Router has moved to expo/expo -- The File-based router for universal React Native apps
https://docs.expo.dev/routing/introduction/
1.37k stars 114 forks source link

Status Bar in _layout has no effect #754

Closed andrew-levy closed 8 months ago

andrew-levy commented 1 year ago

Which package manager are you using? (Yarn is recommended)

Yarn

Summary

Adding a StatusBar component from expo-status-bar in a layout file has no effect on the status bar. Works as expected on SDK 48, v1 but not in SDK 49, v2 which leads me to believe this may be a bug with layout routes.

I put a console.log in the expo status bar library and it seems to set the correct status bar color, but then quickly rerenders with the dark value, causing it to have no effect. Not sure where that second rerender is coming from, possibly related to some of the other issues?

Using: SDK 49 Expo Router v2 Expo Status Bar 1.6.0

Minimal reproducible example

import { Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";

export default function RootLayout() {
  return (
    <>
      <StatusBar style={"light"} />
      <Stack />
    </>
  );
}
louislatreille commented 1 year ago

I'm having the same issue using the same versions.

In addition to this, the statusBarColor in the screen options of layouts has the same issue.

<Stack
  screenOptions={{
    headerShown: false,
    statusBarColor: "dark", <==== doesn't do anything
  }}
/>
louislatreille commented 1 year ago

Additional information: It seems to be happening on Android only. iOS seems to be working fine.

andrew-levy commented 1 year ago

I originally had the issue on ios, but i'll check again and see if it's still an issue

update: confirmed still an issue on iOS for me. @louislatreille how did you get it working on iOS?

corasan commented 1 year ago

This is an issue for me as well on iOS. Only works when using StatusBar on each screen individually.

louislatreille commented 1 year ago

Haven't done anything to make it work on iOS.

To give more context, I've migrated from react-navigation to expo-router lately. I haven't changed anything to the status bar theme that I had before. I.e. I have the StatusBar component in one of my top level component.

louislatreille commented 1 year ago

I've done a bit more investigation, and it seems that what is overriding the status bar style is this: https://github.com/expo/router/blob/f69e31c84a83ceb6d678dfb8aeed708974d301a8/packages/expo-router/src/ExpoRoot.tsx#L74

{/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
{!hasViewControllerBasedStatusBarAppearance && (
  <StatusBar style="auto" />
)}

If I remove the StatusBar component from there in my node_modules, my style is applied properly.

It is unclear to me what the comment there means. From my understanding, the ExpoRoot component is the top most component of the application. There's nothing in my app that is higher than that. Perhaps the entry file was set differently in expo-router v1?

It is also unclear to me if expo-router should be setting the status bar style at all. Although, there definitely could be a good reason that I am not aware of.

dserranog1 commented 1 year ago

I was having the same issue, no matter what style I set to my StatusBar in my _layout component the StatusBar was using the corresponding style based on what theme was set by iOS (which in my case was dark, so StatusBar was always light), this might be a bug. I found a workaround by explicitly setting the userInterfaceStyle to light in my app.json as explained here. After this, setting the StatusBar style worked fine.

zackify commented 1 year ago

@EvanBacon can we get this merged. i guess for now we can patch package the line, thanks @louislatreille

In case this helps anyone:

diff --git a/node_modules/expo-router/src/ExpoRoot.tsx b/node_modules/expo-router/src/ExpoRoot.tsx
index 3e9bcbe..7a8387b 100644
--- a/node_modules/expo-router/src/ExpoRoot.tsx
+++ b/node_modules/expo-router/src/ExpoRoot.tsx
@@ -69,10 +69,7 @@ export function ExpoRoot({
           >
             {children}

-            {/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
-            {!hasViewControllerBasedStatusBarAppearance && (
-              <StatusBar style="auto" />
-            )}
+          
           </SafeAreaProvider>
         </GestureHandlerRootView>
       </ParentWrapper>
Azanniel commented 1 year ago

Not only is it affecting the style but also the "translucent" property. In my case, it is not becoming translucent.

Azanniel commented 1 year ago

In an excerpt from the file expo-router/src/views/Navigator.tsx

Instead of using SafeAreaView I added a View:

export function DefaultNavigator() {
  return (
    <View style={{ flex: 1 }}>
      <Navigator>
        <QualifiedSlot />
      </Navigator>
    </View>
  );
}

With this, the StatusBar worked with the translucent property:

export default function Page() {
  return (
    <View
      style={{
        flex: 1,
        backgroundColor: 'red',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <Text>Hello world from route based file</Text>

      <StatusBar
        style="dark"
        backgroundColor="transparent"
        translucent={true}
      />
    </View>
  )
}

I just made a small correction, but I don't have enough knowledge to implement this efficiently. I wanted to leave my contribution here by discovering the problem in question.

If I'm mistaken about the purpose of the current implementation, please help me understand 😅

Taraslysak commented 8 months ago

This issue re-appeared in expo-router v3, expo SDK 50 on android devices (Samsung A21 specifically). When StatusBar is declared in _layout.ts files it is ignored and now there apparently is no node_modules/expo-router/src/ExpoRoot.tsx to make the fix

zackify commented 8 months ago

Here’s the patch I’m using in v3.

diff --git a/node_modules/expo-router/build/ExpoRoot.js b/node_modules/expo-router/build/ExpoRoot.js index 7db529d..47908f9 100644 --- a/node_modules/expo-router/build/ExpoRoot.js +++ b/node_modules/expo-router/build/ExpoRoot.js @@ -57,7 +57,7 @@ function ExpoRoot({ wrapper: ParentWrapper = react_1.Fragment, ...props }) { initialMetrics={INITIAL_METRICS}> {children} {/ Users can override this by adding another StatusBar element anywhere higher in the component tree. /}

arasrezaei commented 8 months ago

same here

marklawlor commented 8 months ago

This should be resolved in v3.

If you are still having this issue, please create a new issue in the main repo https://github.com/expo/expo with a reproduction of your issue and information on what devices you are testing on.

You should not need to patch Expo Router. Please demonstrate what you are trying to achieve so we can either provide assistance or implement a fix.

This repo (and v2) is in maintenance mode. I'm closing this issue as this is fixed in v3 and does not warrant a backport to v2.

vitorcamachoo commented 7 months ago

Still have this issue on v3. This fixed my problem, although is a temporary solution.

MariuzM commented 7 months ago

This is still an issue with latest expo now :(

arasrezaei commented 7 months ago

Yes I used

Here’s the patch I’m using in v3.

diff --git a/node_modules/expo-router/build/ExpoRoot.js b/node_modules/expo-router/build/ExpoRoot.js index 7db529d..47908f9 100644 --- a/node_modules/expo-router/build/ExpoRoot.js +++ b/node_modules/expo-router/build/ExpoRoot.js @@ -57,7 +57,7 @@ function ExpoRoot({ wrapper: ParentWrapper = react_1.Fragment, ...props }) { initialMetrics={INITIAL_METRICS}> {children} {/ Users can override this by adding another StatusBar element anywhere higher in the component tree. /}

  •    {!hasViewControllerBasedStatusBarAppearance && <expo_status_bar_1.StatusBar style="auto"/>}
  •    {/* {!hasViewControllerBasedStatusBarAppearance && <expo_status_bar_1.StatusBar style="auto"/>} */}
     </react_native_safe_area_context_1.SafeAreaProvider>
    </ParentWrapper>);

    };

Yes it's still an issue on android. I used this patch to fix it

MariuzM commented 7 months ago

im on iOS and having this issue

dylancom commented 7 months ago

As the package moved I think it should be reported here: https://github.com/expo/expo/

jatinhemnani01 commented 7 months ago

facing the same problem, how do I fix it?

marjus15 commented 7 months ago

I've done a bit more investigation, and it seems that what is overriding the status bar style is this:

https://github.com/expo/router/blob/f69e31c84a83ceb6d678dfb8aeed708974d301a8/packages/expo-router/src/ExpoRoot.tsx#L74

{/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
{!hasViewControllerBasedStatusBarAppearance && (
  <StatusBar style="auto" />
)}

If I remove the StatusBar component from there in my node_modules, my style is applied properly.

It is unclear to me what the comment there means. From my understanding, the ExpoRoot component is the top most component of the application. There's nothing in my app that is higher than that. Perhaps the entry file was set differently in expo-router v1?

It is also unclear to me if expo-router should be setting the status bar style at all. Although, there definitely could be a good reason that I am not aware of.

This worked for me thank you

karanmartian commented 7 months ago

this is happening even with React Navigation 5.x and Expo SDK 49/50. if i use Navigation 6.x it works

0horaa commented 7 months ago

same here

julian-gargicevich commented 7 months ago

Same issue

karanmartian commented 7 months ago

Please fix this issue asap, as I want to use React Navigation 5.x with SDK 50. I am seeing some white blank screen after splash screen momentarily when i use 6.x with SDK 50 but it used to work much smoother which 5.x and sdk 48. so if you can just make 5.x and sdk 50 work together so that this issue is not found with this combination.

marklawlor commented 7 months ago

This repo is in maintenance mode and not monitored for support issues. If your having an issue, please report on the main report https://github.com/expo/expo/.

@karanmartian SDK 50 supports @react-navigation/native: ^6.0.2`. You free to use 5.x, but we will not prioritise fixing issues for unsupported versions outside the SDK version range. There are typically breaking changes between major versions that make backwards compatibility very difficult.

karanmartian commented 7 months ago

@marklawlor understood, but the issue is that i am seeing a white screen momentarily just after the splash screen on sdk 50 and react navigation 6.x. This was not happening on sdk 48 and 5.x. Although the status bar issue is solved the white screen issue surfaces. Any idea what could be the reason for this?

marklawlor commented 7 months ago

Like I said earlier, this repo is in maintenance mode and we are not monitoring support issues here. This is not the place to ask that question. Please create an issue at https://github.com/expo/expo/ and follow the issue template.

I can only provide very limited assistance without a minimal reproduction of the problem. This is not a reported problem I'm aware of, so I can't provide assistance without you providing more information.

denzelcurry95 commented 5 months ago

Hey there,

we have a workaround for styling the status bar in _layout, it looks like this:

import {NativeModules, processColor} from 'react-native';
import {useEffect} from "react";
const { StatusBarManager } = NativeModules;

export default function Root() {
  useEffect(() => {
    StatusBarManager.setColor(processColor("#000000"), false);
    StatusBarManager.setStyle("light-content");
  }, []);

...
(other code)
...
mathura333 commented 4 months ago

Looks like this issue is still there

mathura333 commented 4 months ago

Hey there,

we have a workaround for styling the status bar in _layout, it looks like this:

import {NativeModules, processColor} from 'react-native';
import {useEffect} from "react";
const { StatusBarManager } = NativeModules;

export default function Root() {
  useEffect(() => {
    StatusBarManager.setColor(processColor("#000000"), false);
    StatusBarManager.setStyle("light-content");
  }, []);

...
(other code)
...

This did not work for me

mathura333 commented 4 months ago

Solution Did this hack and it worked for me

import { useEffect } from 'react';
import { Slot, usePathname } from 'expo-router';
import { StatusBar } from 'react-native';

const Layout = () => {
  const pathname = usePathname();

  useEffect(() => {
    setTimeout(() => {
      StatusBar.setBarStyle('light-content');
    }, 0);
  }, [pathname]);

  return (
    <>
      <StatusBar barStyle="light-content" />

      <Slot />
    </>
   );
};

export default Layout;
JoelSoy commented 2 months ago

### This is my solution: I think that when using <StatusBar/> and then <Stack/> Stack overwrites its own values ​​making <StatusBar/> obsolete:

<Stack
        screenOptions={{
          statusBarColor: "#0B0B0B", //backgroundColor for Statusbar
          statusBarStyle: "light",  //color for elements the icons
        }}
      />

I recommend customizing this for each page:

<Screen>
      <Stack.Screen
        options={{
          headerStyle: { backgroundColor: "#ffee00" },
          headerTintColor: "black",
          statusBarStyle: "dark",
PetrusBorges commented 1 month ago

Solution Did this hack and it worked for me

import { useEffect } from 'react';
import { Slot, usePathname } from 'expo-router';
import { StatusBar } from 'react-native';

const Layout = () => {
  const pathname = usePathname();

  useEffect(() => {
    setTimeout(() => {
      StatusBar.setBarStyle('light-content');
    }, 0);
  }, [pathname]);

  return (
    <>
      <StatusBar barStyle="light-content" />

      <Slot />
    </>
   );
};

export default Layout;

this works for me, is unbelivable that we need to put this quick fix to statusbar work ok

bitsmanent commented 1 month ago

@JoelSoy That worked. Thanks!

harmony-netizen commented 1 month ago

This one works for me on android, thanks so much @JoelSoy ! But on iOS seems to cause an issue :

If you want to change the appearance of status bar, you have to change
UIViewControllerBasedStatusBarAppearance key in the Info.plist to YES

RNScreens::RNScreensTurboModule::getPropertyNames(facebook::jsi::Runtime&)

Seems for iOS, I need to use userInterfaceStyle in app.json

### This is my solution: I think that when using <StatusBar/> and then <Stack/> Stack overwrites its own values ​​making <StatusBar/> obsolete:

<Stack
        screenOptions={{
          statusBarColor: "#0B0B0B", //backgroundColor for Statusbar
          statusBarStyle: "light",  //color for elements the icons
        }}
      />

I recommend customizing this for each page:

<Screen>
      <Stack.Screen
        options={{
          headerStyle: { backgroundColor: "#ffee00" },
          headerTintColor: "black",
          statusBarStyle: "dark",
karlhorky commented 5 days ago

The <StatusBar> component can be used again starting in Expo Router v4.0.0-preview.0 🎉

References: