React Native - Navigation navigates but does not render elements on android/ios but renders on web perfectly - react-native

For some reason I can see the elements when run on web (using Expo) and they render perfectly when I click "Run in web browser".
However when I try to do it on iOS or Android, it just shows a blank screen and only shows the LinearGradient.
When I run the Android Emulator and combine it with the React Native Dev tool, I can see the elements in the devtool but they dont show up in the emulator. The component I try to render is called Login.tsx and If i copy all the content in Login.tsx to my App.tsx it renders perfectly on Web, Android and iOS.
What am I doing wrong?
const Stack = createNativeStackNavigator();
const Navigation: React.FC = () => {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Login"
>
<Stack.Screen
name="Login"
component={Login}
/>
<Stack.Screen
name="LostPassword"
component={LostPassword}
/>
<Stack.Screen
name="Register"
component={Register}
/>
</Stack.Navigator>
</NavigationContainer>)
}
export default Navigation;
const App: React.FC = () => {
return (
<LinearGradient
colors={["#2D1C96", '#190E60']}
style={styles.linearGradient}
>
<View style={styles.container}>
<Navigation />
<Toast ref={(ref) => Toast.setRef(ref)} />
</View>
</LinearGradient>
);
}

Solved it.
For anyone facing the same issue:
NavigationContainer should not be inside View. It should be used as a root component

Related

Expo React-Native Web Browser Back Button

I'm looking at using React-Native and Expo to build a web app. The only real issue I'm running into is allowing the use of the browser back button. I'm currently using #react-navigation/native to navigate between screens.
Unfortunately, when changing screens, the browser doesn't seem to register this as a change of page and so the browser back button never works. I could certainly use the standard back button used within the app to navigate back but I'd like people to be able to use the browser back button as that's more intuitive. I'm using the following in my App.js:
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const App = () => {
...
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
)
};
export default () => {
return (
<App />
);
};
So, is it possible using Expo and React-Native to allow the use of the browser back button for apps built for the web?

How to make a stack navigator cover entire screen using React Navigation

I am building a React Native project with Expo. For navigation, I am using react-navigation 6.0 with the following code for my main component:
export default class App extends Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName={'SignIn'} screenOptions={{
headerShown: false
}}>
<Stack.Screen name="SignIn" component={SigninScr} />
<Stack.Screen name="SignUp" component={SignupScr} />
<Stack.Screen name="EmailVerification" component={EmailVerificationScr} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
This works fine, but I haven't been able to make Stack.Navigator cover the entire screen. There is a weird area that's not covered by the Stack.Navigator:
I was reading through some of the documentation about stack navigator, but couldn't find any props or styling to force it to cover 100% of the screen. Does anyone know how to accomplish this?

Adding background color to app.js on react-native

I want to add a default color for all my screens on react-native. My entry file doesn't have a default react-native component that takes in styles as prop. Hence, I'll be asking "How to add styles when Navigation container is present". I have tried adding the cardStyle prop on Drawer.Screen but it doesn't work.
Here's a sample of my code
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name='SignUp' component={SignUp} />
<Drawer.Screen name='Reset Password' component={ResetPassword}/>
<Drawer.Screen name="Forgot Password" component={ForgotPasswordScreen} />
<Drawer.Screen name='Login' component={Login} />
<Drawer.Screen name="Verify Email" component={EmailVerification} />
</Drawer.Navigator>
</NavigationContainer>
Simply we have to create a Root Component in which we can put the background color.
For Example.
Create a Root Component with background color:
const RootComponent = props => {
return (
<View style={{ flex: 1, backgroundColor: "YOUR_BACKGROUND_COLOR" }} >
{props.children}
</View>
)
}
export default RootComponent;
Now we can import the Root Component in our screens in which screens we are supposed to show the same background color.
for Example:
const HomeScreen = props => {
return (
<RootComponent>
{
/* YOUR HOME SCREEN COMPONENTS... */
}
</RootComponent>
)
}

react native splash page warning

I have made an splash page looks like this:
export default class Splash extends Component {
performTimeConsumingTask = async () => {
return new Promise((resolve) =>
setTimeout(() => {
resolve('result');
}),
);
};
async componentDidMount() {
const data = await this.performTimeConsumingTask();
// const navigation = useNavigation();
if (data !== null) {
this.props.navigation.navigate('BottomMainNavgigation');
}
}
render() {
return (
<View style={styles.viewStyles}>
{/* <Text style={styles.textStyles}>Welcome</Text> */}
<Image
style={styles.tinyLogo}
source={{
uri: URL.logov2,
}}
/>
</View>
);
}
}
THen I use this like this, in my navigation:
const RootStackScreen = (props) => {
const [t] = useTranslation();
return (
<SplashRootStack.Navigator>
<SplashRootStack.Screen
name="Main"
component={Splash}
options={{headerShown: false, headerBackTitle: t('back')}}
/>
<SplashRootStack.Screen
name="BottomMainNavgigation"
component={BottomMainNavgigation}
options={{headerShown: false, headerBackTitle: t('back')}}
/>
</SplashRootStack.Navigator>
);
};
and also:
<PaperProvider theme={MyTheme}>
<NavigationContainer linking={linking} fallback={<Splash />}>
<RootStackScreen />
</NavigationContainer>
</PaperProvider>
and like this in my app.js:
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={<Splash />} persistor={persistor}>
<Suspense fallback={<Splash />}>
<Navigation />
</Suspense>
</PersistGate>
</Provider>
);
};
export default App;
when I run the application it looks like this:
there is a warning :
I get this warning with id= 0, 1 and 2 and I get this warning also:
what have I donr incorrectly ad how can I remove these warnings, also when I load the app in the emulator, I get a white screen for few seconds before I get my own splash page and then to my app.
how can I do this better?
You are using Splash component in redux persist as a loader and in your Splash component there isn't any navigation prop available because it's a parent component and not the part of navigation tree you need to use switch navigator for the same purpose but with the current structure navigation will not work unless you move navigation part inside the navigator tree. Now the solution is,
Use only splash as a static UI component.
Move you navigation or componentDidMount logic inside the stack navigator.
Add simple Activity indicator as fallback.
<PersistGate
loading={<ActivityIndicator style={{top: '45%'}}
animating color={theme.appColor} size='large' />}
persistor={ReduxStore.persistor}>
<Navigator />
</PersistGate>
Your warnings
Undefined is not an object :
The problem is that you are using the Splash as the fallback component so until your deeplink is resolved Splash would be displayed and the Splash here is not part of navigation which will not get the 'navigation' prop so you are getting the warning.
Same for the other higher order components like PersistGate and suspense you can given the splash for everything and all this is outsider navigation.
resolution : Use the activity indicator instead of splash for the fallback
This is due to one of your middleware in redux taking longer, better check your redux middleware.
White screen,
this is whats causing the white screen maybe caused by the same reason as your middleware warning or the component did mount of the splash screen. And you have several providers so better remove one or two and check whats causing that.
You can check this sample to get an idea on using splash screens and authentication.
https://snack.expo.io/#guruparan/rnn-v5

IntialParams on a Tab Navigator Screen is undefined (react navigation v5)

I'm trying to pass an initialParam prop to a TabNavigator screen. It is meant to be a login piece of local state, just doing a proof of concept. It works fine with the stack navigator screen, but the route.params on the tab screen is undefined. What am I doing wrong?
Also, I'm pretty sure this will have to change as far as state management goes, but I wanted to make sure I could simply change the state in the parent App and have it take effect. It works on the stack screen, meaning I can call setLoggedIn(true) and it will take me to the tab navigator. But I can't go back...
const Track = () => {
return (
<TrackStack.Navigator>
<TrackStack.Screen
name='TrackListScreen'
component={TrackListScreen}
/>
<TrackStack.Screen
name='TrackDetailScreen'
component={TrackDetailScreen}
/>
</TrackStack.Navigator>
);
};
const App = () => {
const [loggedIn, setLoggedIn] = useState(false);
return (
<NavigationContainer>
{loggedIn ? //is logged in
(
<MainTab.Navigator>
<MainTab.Screen
name='TrackCreateScreen'
component={TrackCreateScreen}
initialParams={{ setLoggedIn }}
/>
<MainTab.Screen
name='AccountScreen'
component={AccountScreen}
/>
<MainTab.Screen
name='Track'
component={Track}
/>
</MainTab.Navigator>
) : (
<LoginStack.Navigator>
<LoginStack.Screen
name='SignupScreen'
component={SignupScreen}
initialParams={{ setLoggedIn }}
/>
<LoginStack.Screen
name='SigninScreen'
component={SigninScreen}
/>
</LoginStack.Navigator>
)}
</NavigationContainer>
);
};
export default App;