I received warning when tried to hide bottom nav in specific screen. The warning is 'Cannot update a component from inside the function body of a different component', So what I'm trying to do is that I've a home screen and when I navigate to detail screen the bottom nav is going to disappear/hidden. my code as below:
ProductNavigation.js my stack navigation
import 'react-native-gesture-handler';
import React, {useState, useEffect} from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { createStackNavigator } from '#react-navigation/stack'
import MainScreen from '../screen/MainScreen'
import DetailScreen from '../screen/DetailScreen'
const Stack = createStackNavigator();
const ProductNavigation = ({navigation, route}) => {
if (route.state) {
navigation.setOptions({
tabBarVisible: route.state.index > 0 ? false: true
})
}
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={MainScreen} />
<Stack.Screen name="Detail" component={DetailScreen} options = {({ route }) => ({title:
route.params.productName })}/>
</Stack.Navigator>
)
}
export default ProductNavigation;
BottomTabNav.js my bottom navigation
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import Ionicons from 'react-native-vector-icons/Ionicons'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
import ProductNavigation from './ProductNavigation'
import SettingScreen from '../screen/SettingScreen'
const BottomTab = createBottomTabNavigator();
const BottomTabNav = ({ navigation, route }) => {
return (
<BottomTab.Navigator>
<BottomTab.Screen
name="Home"
component={ProductNavigation}
options={{
tabBarLabel: "Home",
tabBarIcon:({color, size}) => (
<Ionicons name="home-outline" color={color} size={size} />)
}} />
<BottomTab.Screen
name="Settings"
component={SettingScreen}
options={{
tabBarLabel: "Settings",
tabBarIcon: ({color, size}) => (
<Ionicons name="settings-outline" color={color} size={size} />)
}} />
</BottomTab.Navigator>
)
}
export default BottomTabNav
yes it got hidden in detail screen, but why there is a warning? where should I edit or change my code?
Looking at the docs for navigation.setOptions (https://reactnavigation.org/docs/navigation-prop/#setoptions) there they put the logic in the useLayoutEffect hook.
try changing:
import React from 'react'
...
if (route.state) {
navigation.setOptions({
tabBarVisible: route.state.index > 0 ? false: true
})
}
to
import React, { useLayoutEffect } from 'react'
...
...
useLayoutEffect(() => {
if (route.state) {
navigation.setOptions({
tabBarVisible: route.state.index > 0 ? false: true
})
}
}, [navigation, route])
Related
I'm building a React Native app with React Navigation. I'm using Drawer Screens.
I need that if a Screen is opened, and I touch in its NavigatorButton, the screen will reset or at least recive an event.
NOTE: I'm not trying the screen reset when I touch to another, I need that if the screen is opened, reset it touching in his navigator tab
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import GameScreen from "./screens/GameScreen";
import { createDrawerNavigator } from "#react-navigation/drawer";
export default function App(params: { navigation: any }) {
const Drawer = createDrawerNavigator();
return (
<NavigationContainer>
<Drawer.Navigator useLegacyImplementation initialRouteName="Home">
<Drawer.Screen
name="Home"
options={{
title: "HomePage",
unmountOnBlur: true,
}}
component={GameScreen}
listeners={{
drawerItemPress: (e) => {},
}}
/>
<Drawer.Screen name="Nuevo juego" component={GameScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
SOLUTION
Well, I found a way to get "navigation" inside NavigationContainer. I hope it helps someone
import React from 'react'
import { NavigationContainer } from '#react-navigation/native'
import GameScreen from './screens/GameScreen'
import {
createDrawerNavigator,
DrawerContent,
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from '#react-navigation/drawer'
export default function App(params: { navigation: any }) {
const Drawer = createDrawerNavigator()
const CustomDrawers = (props: any) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem
label={'Nuevo juego'}
onPress={() =>
props.navigation.reset({
index: 0,
routes: [{ name: 'Home' }],
})
}
/>
</DrawerContentScrollView>
)
}
return (
<NavigationContainer>
<Drawer.Navigator
useLegacyImplementation
initialRouteName="Home"
drawerContent={(props) => CustomDrawers(props)}>
<Drawer.Screen
name="Home"
options={{
title: 'Continuar',
// unmountOnBlur: true,
}}
component={GameScreen}
/>
</Drawer.Navigator>
</NavigationContainer>
)
}
I have this code that come directly from the doc of react navigation link here.
import * as React from 'react';
import { Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const MyStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Welcome' }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
const HomeScreen = ({ navigation }) => {
return (
<Button
title="Go to Jane's profile"
onPress={() =>
navigation.navigate('Profile', { name: 'Jane' })
}
/>
);
};
const ProfileScreen = ({ navigation, route }) => {
return <Text>This is {route.params.name}'s profile</Text>;
};
const App = () => {
return (
<NavigationContainer>
<HomeScreen />
</NavigationContainer>
);
};
export default App;
and when i click on the button i have this error : undefined is not an object. can you help me found what's wrong ?
That just to test at the end i want different page in my app and navigate into,
i don't understant why all the different page is on the same file ...
Thank you,
have good coding day
The Reason Behind this is you are used HomeScreen component inside App component.You Have to use MyStack component inside the App component.
then you get error about NavigationContainer you have to use NavigationContainer one time not in nested.Please remove NavigationContainer from App component or MyStack component.
also Add ..
import{Text} from 'react-native';
congratulations Your Programm run perfectly.
I Changed small things in your code please copy and then try it will work.
import * as React from 'react';
import { Button,Text} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const MyStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Welcome' }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
const HomeScreen = ({ navigation }) => {
return (
<Button
title="Go to Jane's profile"
onPress={() =>
navigation.navigate('Profile', { name: 'Jane' })
}
/>
);
};
const ProfileScreen = ({ navigation, route }) => {
return <Text>This is {route.params.name}'s profile</Text>;
};
const App = () => {
return (
<MyStack />
);
};
export default App;
Happy Coding
My app has a home screen (HomeScreen.js) with a bottom tab navigator, and it is nested within a stack navigator in App.js. Whenever I try and navigate to the profile screen from the home screen I get the following error:
This error only occurs when I try and set headerTitle to a custom component in App.js. Does anyone know how I can set the header of ProfileScreen to a custom component correctly?
My navigation structure looks like this:
Stack.Navigator
Tab.Navigator
Food (screen)
Friends (screen)
Lists (screen)
Profile (screen)
I am able to set a custom component as the header in Tab.Navigator, but not in Profile
Let me know if more information is needed.
App.js:
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "react-native-screens/native-stack";
import HomeArea from "./screens/HomeScreen";
import ProfileScreen from "./screens/ProfileScreen";
import NavBar from "./componets/NavBar";
import BackSVG from "./assets/BackSVG";
import { Text, View } from "react-native";
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="HomeArea"
component={HomeArea}
options={{ headerShown: false }}
/>
<Stack.Screen
name="ProfileScreen"
component={ProfileScreen}
options={{
headerTitle: props => {
return <Text>Test</Text>;
}
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
HomeScreen.js:
import * as React from "react";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import FoodScreen from "../screens/FoodScreen";
import FriendsScreen from "../screens/FriendsScreen";
import Lunchlists from "../screens/Lunchlists";
import { StyleSheet, View } from "react-native";
import FoodSVG from "../assets/FoodSVG";
import ListSVG from "../assets/ListSVG";
import FriendsSVG from "../assets/FriendsSVG";
import NavBar from "../componets/NavBar";
import UserSVG from "../assets/UserSVG";
const Tab = createBottomTabNavigator();
export default function HomeScreen({ navigation }) {
return (
<Tab.Navigator
screenOptions={{
tabBarStyle: styles.navBar,
tabBarActiveTintColor: "#fff",
tabBarShowLabel: false,
header: () => (
<NavBar
symbolRight={UserSVG}
symbolLeft={View}
rightPressEvent={() => navigation.navigate("ProfileScreen")}
/>
)
}}>
<Tab.Screen
name="Food"
component={FoodScreen}
options={{
tabBarLabel: "Food",
tabBarIcon: ({ color, size }) => {
return <FoodSVG width={size} height={size} color={color} />;
}
}}
/>
<Tab.Screen
name="Friends"
component={FriendsScreen}
options={{
tabBarLabel: "Friends",
tabBarIcon: ({ color, size }) => {
return <FriendsSVG width={size} height={size} color={color} />;
}
}}
/>
<Tab.Screen
name="Lunchlists"
component={Lunchlists}
options={{
tabBarLabel: "Lunchlists",
tabBarIcon: ({ color, size }) => {
return <ListSVG width={size} height={size} color={color} />;
}
}}
/>
</Tab.Navigator>
);
}
const styles = StyleSheet.create({
navBar: {
backgroundColor: "#5A4664"
}
});
I imported createNativeStackNavigator from the wrong package. In App.js I instead imported it using import { createNativeStackNavigator } from "#react-navigation/native-stack";, which solved my problems.
This is my first React Native project and I am stuck and need help. Following is my code. What I am trying to do is following.
Landing screen will have list of all projects and bottom tab menu.
Once someone clicks on project, it will open project details page.
App.Js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React from 'react';
import App from './src';
import { Provider as PaperProvider } from 'react-native-paper';
export default App;
src/navigations/index.js
import * as React from 'react';
import { Text, View, StyleSheet, FlatList, SafeAreaView } from 'react-native';
import { List, Button, TextInput, FAB, Avatar, Card, Title, Paragraph } from 'react-native-paper';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createStackNavigator} from '#react-navigation/stack';
import ProjectList from '_scenes/projects';
import NewProject from '_scenes/projects/addproject';
import ProjectDetail from '_scenes/projects/projectdetails';
import Settings from '_scenes/settings';
const Tab = createBottomTabNavigator();
const Projects = ({ navigation }) => (
<ProjectList navigation={navigation} />
);
function SettingsScreen( { navigation} ) {
return (
<Settings />
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="HomeScreen">
<Tab.Screen name="Home" component={Projects} options={{ tabBarBadge: 3 }}/>
<Tab.Screen name="Settings" component={SettingsScreen} options={{ tabBarBadge: 2 }}/>
</Tab.Navigator>
</NavigationContainer>
);
}
src/scenes/projects/index.js
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import { Item, List, Button } from 'react-native-paper';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createStackNavigator} from '#react-navigation/stack';
import NewProject from '_scenes/projects/addproject';
import ProjectDetail from './projectdetails';
ProjectList = ({ navisation }) => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('http://xxx.xxx.xxx.xxx/projects')
.then((response) => response.json())
.then((json) => setData(json))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
function Projects ( {navigation }) {
return (
<View style={{ flex: 1, padding: 24 }}>
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={renderProject}
/>
</View>
)
}
const renderProject = ({ navigation, item }) => (
<List.Item
title={item.title}
description={item.description}
onPress={() => navigation.navigate('ProjectDetails')}
/>
);
const AddProject = ({ navigation }) => (
<NewProject />
);
function ProjectDetails({navigation}) {
return (
<ProjectDetail />
);
}
function Chat({navigation}) {
return (
<View>
<Text>Chat</Text>
</View>
);
}
const Stack = createStackNavigator();
return (
<Stack.Navigator>
<Stack.Screen title="Home" name="Home" component={Projects} options={{headerShown: false}}/>
<Stack.Screen title="Add Project" name="AddProject" component={AddProject} />
<Stack.Screen title="Project Details" name="ProjectDetails" component={ProjectDetails} />
<Stack.Screen title="Chat" name="Chat" component={Chat} />
</Stack.Navigator>
);
};
export default ProjectList;
if you see "renderProject" I want to navigate to "ProjectDetails" when clicked. but I receive error 'TypeError: undefined is not an object (evaluating 'navigation.navigate')' let me know what is wrong?
I took a simple example of NavigationContainer. I have a main Screen <Tab.Screen name="Home" component={HomeScreen} />
I created a new Component HomeScreen then connected with App.js
In my component HomeScreen I fetch data.
I does not work. My error:
Couldn't find a 'component' or 'children' prop for the screen 'Home'. This can happen if you passed 'undefined'.
How could I do it? Thanks!
App.js
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { HomeScreen } from './src/screens/HomeScreen';
import { SignInScreen } from './src/screens/SignInScreen';
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SignInScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
HomeScreen.js
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
export default HomeScreen = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => setData(json.movies))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
});
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.title}, {item.releaseYear}</Text>
)}
/>
)}
</View>
);
};
you are exporting default export default HomeScreen but importing with destructing.
Change
import { HomeScreen } from './src/screens/HomeScreen';.
To
import HomeScreen from './src/screens/HomeScreen';