Passing a function as prop in react native react navigation - react-native

Hi I want to add a function to record the value of input and want to use it in all components and input is in another component and I want to pass a function from App.js to that component but it does not work please help me out \
Please note that the function should be in the App.js passed to Component.js through a Navigator
//App.JS
import React,{useState, useEffect} from "react";
import {
Text,
Link,
HStack,
Center,
Heading,
Switch,
useColorMode,
NativeBaseProvider,
extendTheme,
VStack,
Box,
} from "native-base";
import NativeBaseIcon from "./components/NativeBaseIcon";
import { Platform } from "react-native";
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import HomeScreen from "./Comp/HomeScreen";
import { NavigationContainer } from "#react-navigation/native";
import Location from "./Comp/Location";
export default function App() {
const [api, setapi] = useState(process.env.REACT_APP_API_KEY)
const api_1 = () => {
setapi(process.env.REACT_APP_API_KEY_2)
}
const api_2 = () => {
setapi(process.env.REACT_APP_API_KEY_3)
}
const [value, setvalue] = useState("London")
const handlechange = (e) => {
setvalue(e.target.value)
console.log('value :>> ', value);
}
const Tab = createMaterialBottomTabNavigator();
return (
<NativeBaseProvider>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen initialParams={{value:value, change:handlechange}} name="Location" component={Location} />
</Tab.Navigator>
</NavigationContainer>
</NativeBaseProvider>
);
}
//Component.js
import { Center, Input, Text } from 'native-base'
import React, {useState} from 'react'
import { ImageBackground } from 'react-native'
import BG from "./Img/BG.png"
export default function Location({ navigation, route }) {
// const [value, setvalue] = useState("London")
// const handlechange = (e) => {
// setvalue(e.target.value)
// console.log('value :>> ', value);
// }
const { change, value } = route.params;
return (
<ImageBackground source={BG}>
<Center minH={"100vh"} w={"90vw"} alignSelf={"center"} alignContent={"center"}>
<Input color={"white"} size="xl" onChange={change} variant="rounded" placeholder="Enter Location" />
<Text color={"white"}></Text>
</Center>
</ImageBackground>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Related

React native navigation not initialized yet

I'm learning react native but I'm having difficulty with navigation, it's returning the error that navigation has not been initialized yet.
I looked for some tutorials, I tried some other ways, I went to the react native navigation documentation and, incredible as it may seem, it's the same as in the documentation... not even the GPT chat haha ​​it didn't help me.
Can someone with experience in react native give me a light?
app.tsx:
import { NavigationContainer } from '#react-navigation/native';
import { createAppContainer } from 'react-navigation';
import StackNavigator from './app/index/navigator';
const AppContainer = createAppContainer(StackNavigator);
const App = () => {
return (
<NavigationContainer>
<AppContainer />
</NavigationContainer>
);
}
export default App;
navigator.tsx?
import { createStackNavigator } from 'react-navigation-stack';
import Index from '.';
import AddNewGrocery from '../components/addNewGrocery'
const StackNavigator = createStackNavigator({
home: { screen: Index, navigationOptions: { headerShown: false } },
addNewGrocery: { screen: AddNewGrocery, navigationOptions: { headerShown: false } },
});
export default StackNavigator;
index.tsx:
const Index = () => {
return (
<View style={styles.container}>
<Text style={styles.title}>Gestão de Compras</Text>
<LastFiveGrocery />
<MonthAverageSpend />
<TotalSpend />
<AddButton />
<StatusBar
translucent={false}
backgroundColor={'rgba(43, 43, 43, 1)'}
barStyle='light-content' />
</View>
);
}
AddButton.tsx:
import React from 'react';
import { StyleSheet, View, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { useNavigation } from '#react-navigation/native';
const AddButton = () => {
const navigation = useNavigation();
const handleAddButtonPress = () => {
navigation.navigate('addNewGrocery' as never);
}
return (
<TouchableOpacity style={styles.addButtonContainer} onPress={handleAddButtonPress}>
<View style={styles.addButton}>
<Ionicons name="ios-add" size={36} color="white" />
</View>
</TouchableOpacity>
);
}
I already tried to use it this way:
AddButton:
const { navigate } = useNavigation<StackNavigationProp<ParamListBase>>();
const handleAddButtonPress = () => {
navigate('addNewGrocery');
}
I've also tried using it this way:
navigator:
const StackNavigator = createAppContainer(createStackNavigator({
Home: { screen: Index },
addNewGrocery: AddNewGrocery,
}));
app.tsx:
import StackNavigator from './app/index/navigator';
const App = () => {
return (
<StackNavigator />
);
}
export default App;
You are using 2 different navigation library in simultaneously:
#react-navigation
react-navigation
Remove react-navigation and refactor the App.js file as below:
import { NavigationContainer } from '#react-navigation/native';
import StackNavigator from './app/index/navigator';
const App = () => {
return (
<NavigationContainer>
<StackNavigator />
</NavigationContainer>
);
}
export default App
StackNavigator should be implemented as per documentation -
https://reactnavigation.org/docs/stack-navigator/#api-definition

navigation.goBack function not working in React Native

StackRoutes.tsx Component (used in App.tsx)
export const StackRoutes = () => {
const Stack = createNativeStackNavigator()
return (
<NavigationContainer>
<Stack.Navigator initialRouteName={Path.introductionScreen}>
<Stack.Screen
name={Path.onBoardingChooseAliasScreen}
options={Options.onBoardingChooseAliasScreen}
component={OnBoardingChooseAlias}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
Options.tsx component (being used in StackRoutes.tsx)
import React from 'react'
import { NativeStackNavigationOptions } from '#react-navigation/native-stack'
import { CustomBackButton } from './CustomBackButton'
const onBoardingChooseAliasScreen: NativeStackNavigationOptions = {
headerLeft: () => { return <CustomBackButton />}
}
export default {
onBoardingChooseAliasScreen,
}
CustomBackButton.tsx component (being used in Options.tsx)
import React from 'react'
import styled from 'styled-components/native'
import SVGimg from 'src/shared/images/greenMarker.svg'
export const CustomBackButton: React.FC<any> = ({ navigation }) => {
return (
<Wrapper onPress={() => navigation.goBack()}>
<SVGimg />
</Wrapper>
)
}
const Wrapper = styled.Pressable``
The CustomBackButton gets displayed as desired, but the goBack() function doesnt work. If i use default back button it works, so i know there is a stack to fall back on.
How do I make the goBack function work?
It seems like CustomBackButton does not have access to navigation
can you try with useNavigation hook
import React from 'react'
import styled from 'styled-components/native'
import SVGimg from 'src/shared/images/greenMarker.svg'
import { useNavigation } from '#react-navigation/native';
export const CustomBackButton: React.FC<any> = () => {
const navigation = useNavigation()
return (
<Wrapper onPress={() => navigation.goBack()}>
<SVGimg />
</Wrapper>
)
}
const Wrapper = styled.Pressable``

Fail Importing expo font

I'm getting this error when trying to import a font with expo font.
null is not an object" (evaluating 'dispatcher.useState')
But the error is for sure related to my font import.
import { NavigationContainer, useNavigation } from '#react-navigation/native';
import { FontAwesome } from '#expo/vector-icons';
import { MaterialCommunityIcons } from '#expo/vector-icons';
import {createStackNavigator} from '#react-navigation/stack';
import { AuthContext } from "./context";
import BottomTabNavigator from "./navigation/tabsNav";
import * as firebase from "firebase";
import Myapp from './instanceFirebase';
import AuthStackScreen from './navigation/authStack';
import { ActivityIndicator } from 'react-native'
import FlashMessage from "react-native-flash-message";
const instanceFirebase = Myapp;
import "firebase/functions";
import "firebase/firestore";
import * as Font from 'expo-font';
console.log("font", Font)
const [fontState, setFontState] = React.useState(false);
const MainStack = createStackNavigator();
const MainStackScreen = () => {
return(
<MainStack.Navigator initialRouteName="mainPage" >
<MainStack.Screen
name="mainPage"
component={BottomTabNavigator} />
</MainStack.Navigator>
)
}
const RootStack = createStackNavigator();
const RootStackScreen = ({ userToken }) => (
<RootStack.Navigator headerMode="none">
{userToken ? (
<RootStack.Screen
name="App"
component={MainStackScreen}
/>
) : (
<RootStack.Screen
headerMode="none"
name="Authstack"
component={AuthStackScreen}
options={{
animationEnabled: false
}}
/>
)}
</RootStack.Navigator>
);
export default function token() {
const [userToken, setUserToken] = React.useState(null);
const Context = {
instanceFirebase: instanceFirebase,
signOut: () => {
setUserToken(null);
},
signIn:() => {
setUserToken(true);
}
}
React.useEffect(() => {
const fetchFont = async () => {
await Font.loadAsync({
Jost: require('./assets/fonts/Jost-Regular.ttf'),
Jost_black: require('./assets/fonts/Jost-Black.ttf')
})
setFontState(true)
}
fetchFont()
firebase.auth().onAuthStateChanged(user => {
if(user){
setUserToken(true)
} else {
setUserToken(null)
}
})
}, [])
if (!fontState) {
return <ActivityIndicator />
} else {
return (
<AuthContext.Provider value={instanceFirebase}>
<NavigationContainer>
<RootStackScreen userToken={userToken} />
<FlashMessage position="top" style={{zIndex:99, flex:1, marginTop:30}}/>
</NavigationContainer>
</AuthContext.Provider>
)
}
}
I checked that expo-font is well import, and it is fine.
I don't understand what is happening, when i comment the code related to the import of the font my app just work. So my error is for sure related to the font import.
I do things correctly ?
Thanks per advance for your help
The right answer from Med El Mobarik:
Indeed i am not supposed to use the useState outside a funcionnal component
const [fontState, setFontState] = React.useState(false);
Nevertheless is there a way to load the font in the root page (at the start of the app/Where the instance of my app is launching) ? I want to avoid to load the font on each page.

Why I get this error: navgation.push is not a function?

I want to push a screen but its not working:
TypeError: navigation.push is not a function. (In 'navigation.push('Restaurants', {
name: params
})', 'navigation.push' is undefined)
Explore.tsx
import { useNavigation } from '#react-navigation/core';
import { NativeStackScreenProps } from '#react-navigation/native-stack';
import React from 'react';
import { StyleSheet, Text, View, Pressable, ScrollView } from 'react-native';
import { RootStackParams } from '../../App';
import Card from '../components/Card';
type PropNav = NativeStackScreenProps<RootStackParams, 'Explore'>;
const Explore = ({ navigation }: PropNav) => {
const handleNavigate = (params: string) => {
navigation.push('Restaurants', { name: params });
};
return (
<View style={{marginTop: 200}}>
<ScrollView>
<Card name="Zum Profil" onPress={(params) => handleNavigate(params)} />
</ScrollView>
</View>
)
};
export default Explore;
App.tsx
import { StatusBar } from 'expo-status-bar';
import { useState } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
import Explore from './src/screens/Explore';
import { NavigationContainer, NavigatorScreenParams } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Profile from './src/screens/Profile';
import Restaurants from './src/screens/Restaurants';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import ProfileIcon from './src/icon/ProfileIcon';
export type RootStackParams = {
Explore: undefined;
Profile: undefined;
RestaurantsStack: NavigatorScreenParams<RestaurantTypesParms>;
Restaurants: {
name: string
}
}
const RootStack = createBottomTabNavigator<RootStackParams>();
export type RestaurantTypesParms = {
Restaurants: {
name: string
}
}
const RestaurantStack = createNativeStackNavigator<RestaurantTypesParms>();
const RestaurantScreen = () => {
return ( <RestaurantStack.Navigator>
<RestaurantStack.Screen name="Restaurants" component={Restaurants} />
</RestaurantStack.Navigator>)
};
export default function App() {
const [text, setText] = useState('');
return (
<NavigationContainer>
<RootStack.Navigator initialRouteName='Explore'
screenOptions={{
headerShown: false,
tabBarActiveTintColor: 'purple'
}}
>
<RootStack.Screen name="Explore" component={Explore}
options={{
tabBarIcon: ({ color, size }) => <ProfileIcon color={color} size={size} />,
tabBarLabel: "Explore"
}}
/>
<RootStack.Screen name="Profile" component={Profile} />
<RootStack.Screen name="RestaurantsStack" component={RestaurantScreen} />
</RootStack.Navigator>
</NavigationContainer>
);
}
But if I use navigation.navigate then it works....
........................................................................................................................................................................................................................................
The push method for the navigation prop is added additional for the StackNavigator. You can compare this with the official documentation.
The stack navigator adds the following methods to the navigation prop:
push​
Pushes a new screen to top of the stack and navigate to it. The method accepts following arguments:
name - string - Name of the route to push onto the stack.
params - object - Screen params to pass to the destination route.
You are not using a Stack.Navigator. You need to install #react-navigation/native-stack and use a different navigator to make this work. I would suggest that you go through this documentation where a full working example is provided.
you can try this.
const handleNavigate = (params: string) => {
navigation.navigate('Restaurants', { name: params });
};
or
const handleNavigate = (params: string) => {
navigation.replace('Restaurants', { name: params });
};
or
const handleNavigate = (params: string) => {
navigation.navigate('RestaurantScreen', { name: params });
};

Error when calling a component react native

I want to create a component like this to check if the user idle or not.
import React, {useState, useEffect, useRef} from 'react';
import {View, PanResponder, StyleSheet} from 'react-native';
const ScreenConponent = ({...props}) => {
console.tron.log(props);
const timerId = useRef(false);
const [timeForInactivityInSecond, setTimeForInactivityInSecond] =
useState(3600);
useEffect(() => {
resetInactivityTimeout();
}, []);
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponderCapture: () => {
console.tron.log('user starts touch');
resetInactivityTimeout();
},
}),
).current;
const resetInactivityTimeout = () => {
clearTimeout(timerId.current);
timerId.current = setTimeout(() => {
console.tron.log('user idle');
}, timeForInactivityInSecond * 1000);
};
return (
<View style={styles.container} {...panResponder.panHandlers}>
{props.children}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default ScreenConponent;
and this is how i call the component
import React, {useState, useEffect} from 'react';
import {View, Text} from 'react-native';
import Screen from '../../components/Screen';
export default function App() {
return (
<Screen>
<View> <Text> Test </Text> </View>
</Screen>
);
}
But when i tried to call the component, i got an error like this error when run the app
anyone have an idea what's wrong with the code? because i can use this method in react (web)
this is the navigation code
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
// import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {NavigationContainer} from '#react-navigation/native';
import ScheduleScreen from '../pages/Schedule';
const Stack = createStackNavigator();
/** Main route */
const MainNavigator = () => {
return (
<Stack.Screen
name="Schedule"
component={ScheduleScreen}
options={{
header: () => null,
}}
/>
</Stack.Navigator>
);
};
const Root = createStackNavigator();
const RootNavigator = () => {
return (
<NavigationContainer>
<Root.Navigator>
<Root.Screen
name="Main"
component={MainNavigator}
options={{header: () => null}}
/>
</Root.Navigator>
</NavigationContainer>
);
};
export default RootNavigator;