Why the goBack function doesn't work? React Native - javascript

I am new in React Native, I am working on an app where I had to add a prefabricated header, which brings a button to which I want to set the option to go back with the function goBack of Navigation, however the button does not Nothing, also I tried with Navigation.navigate ('route'), but the issue continues. I would really appreciate it if you can help with this.
The code:
import { NavigationContainer, useNavigationState} from '#react-navigation/native';
import { NavigationActions } from 'react-navigation';
import { createStackNavigator } from '#react-navigation/stack';
import { Toolbar } from 'react-native-material-ui';
import * as React from 'react';
import { Platform, StatusBar, StyleSheet, View, Text } from 'react-native';
import BottomTabNavigator from '../../navigation/BottomTabNavigator';
import LinkingConfiguration from '../../navigation/LinkingConfiguration';
import CatHome from '../../screens/subScreens/CatHome';
const Stack = createStackNavigator();
export default function Navigator({navigation}) {
const SearchBar= ()=>{
//const { navigate } = this.props.navigation;
return(
<Toolbar
leftElement= {backOption()}
onLeftElementPress= {()=>navigation.goBack()}
//isSearchActive= {true}
style={{
container: styles.searchBar,
}}
centerElement="DIRECTAPP"
searchable={{
autoFocus: true,
placeholder: 'Buscar',
}}
rightElement={{
menu: {
icon: "more-vert",
iconProps : {
size: 30,
color: 'gray',
},
labels: ["Locación", "Contáctanos"]
}
}}
onRightElementPress={ (label) => { console.log(label) }}
/>
);
}
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="dark-content" />}
<NavigationContainer linking={LinkingConfiguration}>
<Stack.Navigator screenOptions={{
headerLeft: null,
headerTitle: props => <SearchBar {...props} />,
headerStyle: {
backgroundColor: '#9acd32',
}
}}>
<Stack.Screen name="Root" component={BottomTabNavigator} />
<Stack.Screen name="CatHome" component={CatHome} />
</Stack.Navigator>
</NavigationContainer>
</View>
);
}
function backOption (){
//const Route=useRoute();
const state = useNavigationState(state => state);
const routeName = (state.routeNames[state.index]);
//console.log(routeName);
if (routeName=='Root') {
return ''
}
else {
return 'arrow-back'
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
searchBar: {
backgroundColor: '#9acd32',
width: '100%',
shadowOffset: { width: 1, height: 13},
shadowOpacity: 0.1,
}
});

Here is the new code:
import { NavigationContainer, useNavigationState, useNavigation } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { Toolbar } from 'react-native-material-ui';
import * as React from 'react';
import { Platform, StatusBar, StyleSheet, View, Text } from 'react-native';
import BottomTabNavigator from '../../navigation/BottomTabNavigator';
import LinkingConfiguration from '../../navigation/LinkingConfiguration';
import CatHome from '../../screens/subScreens/CatHome';
const Stack = createStackNavigator();
export default function Navigator() {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="dark-content" />}
<NavigationContainer linking={LinkingConfiguration}>
<Stack.Navigator screenOptions={{
headerLeft: null,
headerTitle: props => <SearchBar {...props} />,
headerStyle: {
backgroundColor: '#9acd32',
}
}}>
<Stack.Screen name="Root" component={BottomTabNavigator} />
<Stack.Screen name="CatHome" component={CatHome} />
</Stack.Navigator>
</NavigationContainer>
</View>
);
}
function SearchBar (){
const navigation = useNavigation();
//const { navigate } = this.props.navigation;
return(
<Toolbar
leftElement= {backOption()}
onLeftElementPress= {()=>navigation.goBack()}
//isSearchActive= {true}
style={{
container: styles.searchBar,
}}
centerElement="DIRECTAPP"
searchable={{
autoFocus: true,
placeholder: 'Buscar',
}}
rightElement={{
menu: {
icon: "more-vert",
iconProps : {
size: 30,
color: 'gray',
},
labels: ["Locación", "Contáctanos"]
}
}}
onRightElementPress={ (label) => { console.log(label) }}
/>
);
}
function backOption (){
//const Route=useRoute();
const state = useNavigationState(state => state);
const routeName = (state.routeNames[state.index]);
//console.log(routeName);
if (routeName=='Root') {
return ''
}
else {
return 'arrow-back'
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
searchBar: {
backgroundColor: '#9acd32',
width: '100%',
shadowOffset: { width: 1, height: 13},
shadowOpacity: 0.1,
}
});

Related

React Native, passing data between screens when using BottomTabsNavigator

I am trying to make a react native application. I am using Bottom Tab Navigation, and I have 2 screens. On the first screen, a qr code is first scanned, it contains a string, which is written on the screen.
Then I would like to write out the afformentioned string on the second tab.
How can I pass this data between the screens of the Bottom Tab Navigator?
App:
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import QrcodeScreen from './src/screens/QrcodeScreen';
import EttermekScreen from './src/screens/EttermekScreen';
const Tab =createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name='Qrcode' component={QrcodeScreen} />
<Tab.Screen name='Ettermek' component={EttermekScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
QrcodeScreen:
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function QrcodeScreen() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [text, setText] = useState('Not yet scanned')
const askForCameraPermission = () => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})()
}
// Request Camera Permission
useEffect(() => {
askForCameraPermission();
}, []);
// What happens when we scan the bar code
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setText(data)
console.log('Type: ' + type + '\nData: ' + data)
};
// Check permissions and return the screens
if (hasPermission === null) {
return (
<View style={styles.container}>
<Text>Requesting for camera permission</Text>
</View>)
}
if (hasPermission === false) {
return (
<View style={styles.container}>
<Text style={{ margin: 10 }}>No access to camera</Text>
<Button title={'Allow Camera'} onPress={() => askForCameraPermission()} />
</View>)
}
// Return the View
return (
<View style={styles.container}>
<View style={styles.barcodebox}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{ height: 400, width: 400 }} />
</View>
<Text style={styles.maintext}>{text}</Text>
{scanned && <Button title={'Scan again?'} onPress={() => setScanned(false)} color='tomato' />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
maintext: {
fontSize: 16,
margin: 20,
},
barcodebox: {
alignItems: 'center',
justifyContent: 'center',
height: 300,
width: 300,
overflow: 'hidden',
borderRadius: 30,
backgroundColor: 'tomato'
}
});
The screen I would like to print the string:
import { StyleSheet, Text, View } from 'react-native';
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import QrcodeScreen from './QrcodeScreen';
export default function EttermekScreen({ route }) {
const { varisId } = route.params
return (
<View style={styles.container}>
<Text>ÉTTERMEK</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
In EttermekScreen, you already have this line, const { varisId } = route.params, and grabbing from the props route, so you should be good with it.
Assuming you wanna send data in handleBarCodeScanned to EttermekScreen as a parameter called varisId, you could do it this way:
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function QrcodeScreen({navigation}) {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [text, setText] = useState('Not yet scanned')
const askForCameraPermission = () => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})()
}
// Request Camera Permission
useEffect(() => {
askForCameraPermission();
}, []);
// What happens when we scan the bar code
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setText(data);
navigation.navigate('Ettermek', {
varisId: data
});
};
// Check permissions and return the screens
if (hasPermission === null) {
return (
<View style={styles.container}>
<Text>Requesting for camera permission</Text>
</View>)
}
if (hasPermission === false) {
return (
<View style={styles.container}>
<Text style={{ margin: 10 }}>No access to camera</Text>
<Button title={'Allow Camera'} onPress={() => askForCameraPermission()} />
</View>)
}
// Return the View
return (
<View style={styles.container}>
<View style={styles.barcodebox}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{ height: 400, width: 400 }} />
</View>
<Text style={styles.maintext}>{text}</Text>
{scanned && <Button title={'Scan again?'} onPress={() => setScanned(false)} color='tomato' />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
maintext: {
fontSize: 16,
margin: 20,
},
barcodebox: {
alignItems: 'center',
justifyContent: 'center',
height: 300,
width: 300,
overflow: 'hidden',
borderRadius: 30,
backgroundColor: 'tomato'
}
});

React Native NavigationContainer not displaying anything

I'm having an issue using React Native with React Navigator where I'm not seeing a navigation menu at all. I'm using the following code:
App.js:
import "react-native-gesture-handler";
import React from "react";
import { StyleSheet, View } from "react-native";
import { QUATERNARY_COLOR } from "./env.json";
import Header from "./components/header";
import Routes from "./components/routes";
const App = () => {
return (
<View style={styles.home}>
<Header />
<Routes style={styles.routes} />
</View>
);
};
const styles = StyleSheet.create({
home: {
flex: 1,
backgroundColor: QUATERNARY_COLOR,
alignItems: "center",
paddingTop: 60,
},
});
export default App;
Header.js:
import React from "react";
import { StyleSheet, Text, View, Dimensions } from "react-native";
import { APP_NAME, PRIMARY_COLOR, QUATERNARY_COLOR } from "../env.json";
var width = Dimensions.get("window").width;
const Header = () => {
return (
<View style={styles.header}>
<Text style={styles.text}>{APP_NAME}</Text>
</View>
);
};
const styles = StyleSheet.create({
header: {
height: 48,
padding: 8,
paddingRight: 12,
paddingLeft: 12,
backgroundColor: PRIMARY_COLOR,
position: "absolute",
top: 24,
width: width,
alignSelf: "stretch",
textAlign: "center",
},
text: {
color: QUATERNARY_COLOR,
fontSize: 23,
fontWeight: "bold",
textAlign: "center",
},
});
export default Header;
Routes.js:
import React from "react";
import { Text, View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import Home from "../pages/home";
import Login from "../pages/login";
const Stack = createStackNavigator();
const Routes = () => {
return (
<React.Fragment>
<NavigationContainer>
<Stack.Navigator style={{ flex: 1 }}>
<Stack.Screen
name="Home"
component={Home}
options={{ title: "Home" }}
/>
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
</NavigationContainer>
<Text>Hello World</Text>
</React.Fragment>
);
};
export default Routes;
Home.js:
import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View, Image } from "react-native";
import { APP_NAME, APP_VERSION, ENVIRONMENT, PRIMARY_COLOR } from "../env.json";
const Home = () => {
return (
<View style={styles.home}>
<Image
source={require("../assets/android-chrome-192x192-transparent.png")}
style={styles.logo}
/>
<Text h1 style={styles.title}>
{APP_NAME}
</Text>
{ENVIRONMENT !== "Production" ? (
<>
<Text h5 style={styles.version}>
Version {APP_VERSION}
</Text>
<Text h6 style={styles.environment}>
Environment: {ENVIRONMENT}
</Text>
</>
) : (
""
)}
<StatusBar style="auto" />
</View>
);
};
const styles = StyleSheet.create({
title: {
color: PRIMARY_COLOR,
fontSize: 30,
fontWeight: "bold",
},
logo: {
width: 150,
height: 150,
tintColor: PRIMARY_COLOR,
},
version: {
color: PRIMARY_COLOR,
fontSize: 16,
},
environment: {
color: PRIMARY_COLOR,
fontSize: 12,
},
});
export default Home;
Login.js:
import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import * as React from "react";
import { StyleSheet, TextInput, View, Button } from "react-native";
import { API_URL } from "../env.json";
const Login = () => {
const [text, onChangeUsername] = React.useState("");
const [password, onChangePassword] = React.useState("");
return (
<View style={styles.login}>
<Text h1>Login</Text>
<Text h2>Username</Text>
<TextInput
style={styles.input}
onChangeUsername={onChangeUsername}
placeholder="Username"
value={text}
/>
<Text h2>Password</Text>
<TextInput
style={styles.input}
onChangePassword={onChangePassword}
placeholder="Password"
value={password}
secureTextEntry={true}
/>
<Button title="Login" />
<StatusBar style="auto" />
</View>
);
};
const styles = StyleSheet.create({
login: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
},
});
export default Login;
This is what I'm seeing on the Android emulator:
I'm looking to have a navigation menu available to the user and also to have the Home page be the default landing page for the application. How do I do this? What am I doing wrong?
Your Home component must have {flex: 1} on it's container. Specifically in your case you've got 'styles.home' but you don't have that value included in your stylesheet.
And remove the {flex: 1} from the navigator.

React Navigation and React Context

In our App we use a tab navigation and a stack navigation for each tab. We want an array of devices where we could add and delete devices. The array should be available on every tab.
This is our provider
import React from 'react'
const DevicesContext = React.createContext('')
export default DevicesContext
This is our app.js
import React, {useState} from 'react';
import uuid from 'react-native-uuid';
import { NavigationContainer } from '#react-navigation/native';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import { MaterialCommunityIcons } from '#expo/vector-icons';
import { Feather } from '#expo/vector-icons';
import { MaterialIcons } from '#expo/vector-icons';
import HomeStackScreen from "./components/home/HomeStackScreen";
import ConnectStackScreen from "./components/connect/ConnectStackScreen";
import SettingsStackScreen from "./components/settings/SettingsStackScreen";
import DevicesContext from "./components/context/DevicesContext";
const Tab = createMaterialBottomTabNavigator();
const deleteItem = (id) => {
setDevices(prevDevice => {
return prevDevice.filter(device => device.id != id)
})
console.log(devices)
}
const addItem = (device) => {
setDevices(prevDevices => {
return [{id: uuid.v4(), name:device}, ...prevDevices];
})
}
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#E4E4E4"
inactiveColor="#000000"
shifting={true}
labelStyle={{ fontSize: 12 }}
barStyle={{ backgroundColor: '#8DFFBB' }}
>
<Tab.Screen
name="Devices"
component={ConnectStackScreen}
options={{
tabBarLabel: 'Geräte',
tabBarIcon: ({ color }) => (
<MaterialIcons name="devices" size={24} color={color} />
),
}}
/>
<Tab.Screen
name="Home"
component={HomeStackScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Settings"
component={SettingsStackScreen}
options={{
tabBarLabel: 'Einstellungen',
tabBarIcon: ({ color }) => (
<Feather name="settings" size={24} color={color} />
),
}}
/>
</Tab.Navigator>
);
}
export default function App() {
const [devices, setDevices] = useState([
{id: uuid.v4(), name: 'thing 1', ip: 5},
{id: uuid.v4(), name: 'thing 2', ip: 2},
{id: uuid.v4(), name: 'thing 3', ip: 6},
{id: uuid.v4(), name: 'thing 4', ip: 10},
])
return (
<DevicesContext.Provider value={devices}>
<NavigationContainer>
<MyTabs />
</NavigationContainer>
</DevicesContext.Provider>
);
}
this is our connect screen where we can add devices
import React, {useContext, useState} from 'react';
import {Text, View, Button, FlatList, StyleSheet, TouchableOpacity, Image} from 'react-native';
import uuid from 'react-native-uuid';
import ListItem from "../shared/ListItem";
import AddItem from "../shared/AddItem";
import DevicesContext from "../context/DevicesContext";
function ConnectScreen( {navigation}) {
const [devices, setDevices] = useState(useContext(DevicesContext));
const deleteItem = (id) => {
setDevices(prevDevice => {
return prevDevice.filter(device => device.id != id)
})
console.log(devices)
}
const addItem = (device) => {
setDevices(prevDevices => {
return [{id: uuid.v4(), name:device}, ...prevDevices];
})
}
return (
<View style={{padding: 10, flex: 1, justifyContent: 'center'}}>
<View style={styles.AddNormal}>
<AddItem addItem={addItem}></AddItem>
<FlatList style={styles.List} data={devices} renderItem={({item}) => (
<ListItem item={item} deleteItem={deleteItem}></ListItem>
)}/>
</View>
<View style={styles.AddQr}>
<Image source={require('../../img/qr-code-url.png')} style={{ width: 150, height: 150, marginBottom: 10 }} />
<Text style={{ textAlign: 'center', marginBottom: 10 }}>Du kannst außerdem ein Gerät durch das scannen eines Qr-Code hinzufügen</Text>
<TouchableOpacity onPress={() => navigation.navigate('QrCode')}style={styles.btn}>
<Text style={styles.btnText}>Qr-Code scannen</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
List: {
backgroundColor: '#E4E4E4',
},
AddNormal: {
padding: 10, flex: 1,
},
AddQr: {
backgroundColor: '#E4E4E4',
padding: 30,
flex: 1,
marginTop: 20,
marginBottom: 20,
alignItems: 'center'
},
btn: {
backgroundColor: '#8DFFBB',
padding: 9,
margin: 10,
},
btnText: {
color: '#000',
fontSize: 20,
textAlign: 'center',
}
});
export default ConnectScreen;
and this is our main screen
import React, {useState, useContext, useEffect} from 'react';
import {Button, FlatList, SafeAreaView, StatusBar, StyleSheet, Text, TouchableOpacity, View} from "react-native";
import {ServerOnOffSwitch, SendMessage} from "./network";
import DevicesContext from "../context/DevicesContext";
const Item = ({ item, onPress, backgroundColor, textColor }) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.name}</Text>
</TouchableOpacity>
);
function HomeScreen (){
const [devices, setDevices] = useState(useContext(DevicesContext));
const deleteItem = (id) => {
setDevices(prevDevice => {
return prevDevice.filter(device => device.id != id)
})
}
const [selectedId, setSelectedId] = useState(null);
const renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "#b5b5b5" : "#ededed";
const color = item.id === selectedId ? 'white' : 'black';
return (
<Item
item={item}
onPress={() => setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
};
return (
<View style={{padding: 10, flex: 1, justifyContent: 'center'}}>
<View style={{padding: 10, flex: 1}}>
<Text style={styles.DeviceHeader}>Gerät auswählen</Text>
<FlatList
data={devices}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
</View>
<View style={{padding: 10, flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<SendMessage item={selectedId}></SendMessage>
<ServerOnOffSwitch></ServerOnOffSwitch>
</View>
</View>
);
}
const styles = StyleSheet.create({
DeviceHeader: {
fontSize: 22,
paddingBottom: 10,
},
item: {
padding: 10,
backgroundColor: '#f8f8f8',
borderBottomWidth: 1,
borderColor: '#eee',
},
title: {
fontSize: 18,
},
});
export default HomeScreen;
If we add devices in our Connect screen they are getting updated there but not on the homescreen.
Thanks for your help:)
to update context from nested component you must pass the methode setDevices tha will update it.
to pass it do the following steps :
your context shoud be
import React from 'react'
const DevicesContext = React.createContext({
devices: [],
setDevices: () => {}, //methode will update context value
})
export default DevicesContext
App.js should be
//define state
const [devices, setDevices] = React.useState([])
//define constexValue
//we will pass `devices` and also `setDevices` that will update it.
const DevicesContextValue = React.useMemo(() => ({ devices, setDevices}), [devices]);
return (
<DevicesContext.Provider value={DevicesContextValue}>
...
</DevicesContext.Provider>
);
ConnectScreen.js should be
function ConnectScreen(){
const {devices, setDevices} = useContext(DevicesContext);
//call setDevices will update context
....
}
HomeScreen.js should be
function HomeScreen (){
const {devices, setDevices} = useContext(DevicesContext);
//use devices from context in your flatlist and when the context update the result will show in flatlist
....
}

View config getter callback for component 'H' must be a function (received undefined)

Error is:
Invariant Violation: View config getter callback for component 'H' must be a function (received undefined)
I'm using react-native to make application and error happens when I clicked login button in MainLogin.js file. (It has to move to mainpage when clicking login button in login page)
I searched a lot but cannot know what is component 'H'.
attatched index.js (src/screens/index.js) and MainLogin.js (src/screens/MainLogin.js)
<index.js>
import React from 'react';
import {
Text
} from 'react-native';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createBottomTabNavigator } from "react-navigation-tabs";
import LoginScreen from './MainLogin';
import HomeScreen from './MainPage';
import DiaryScreen from './Diarymemo';
import StatScreen from './MoodStatistics';
import CommuScreen from './Community';
import StoreScreen from './Store';
const HomeStack = createStackNavigator(
{
HomeScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Home'}),
}
);
const DiaryStack = createStackNavigator(
{
DiaryScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Diary'}),
}
);
const StatStack = createStackNavigator(
{
StatScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Stat'}),
}
);
const CommunityStack = createStackNavigator(
{
CommuScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Network'}),
}
);
const StoreStack = createStackNavigator(
{
StoreScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Store'}),
}
);
const TabNavigator = createBottomTabNavigator(
InitialRouteName = 'Home',
{
Diary: DiaryStack,
Stat: StatStack,
Home: HomeStack,
Network: CommunityStack,
Store: StoreStack,
},
{
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, horizontal, tintColor}) => {
const {routeName} = navigation.state;
let icon = "▲";
if(routeName === 'Diary'){
icon = "📓";
} else if(routeName === 'Stat'){
icon = "📊"
} else if(routeName === 'Home'){
icon = "🍎"
} else if(routeName === 'Network'){
icon = "👫"
} else if(routeName === 'Store'){
icon = "🛍"
}
// can use react-native-vector-icons
// <Icon name={iconName} size={iconSize} color={iconColor} />
return <Text style={{color: focused && "#46c3ad" || "#888"}}>{icon}</Text>
}
}),
lazy: false,
tabBarOptions: {
activeTintColor: "#46c3ad",
inactiveTintColor: "#888",
},
}
);
const AppStack = createStackNavigator(
{
LoginScreen: LoginScreen,
TabNavigator: {
screen: TabNavigator,
navigationOptions: ({navigation}) => ({
headerShown: false,
}),
},
}
);
export default createAppContainer(AppStack);
<MainLogin.js>
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet
} from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
export default class LoginScreen extends Component{
static navigationOptions = {
headerShown: false,
};
_doLogin(){
// do something
this.props.navigation.replace('TabNavigator')
}
render(){
return (
<View style={styles.container}>
<View style={styles.titleArea}>
<Text style={styles.title}>MoodiBuddy</Text>
</View>
<View style={styles.formArea}>
<TextInput
style={styles.textForm}
placeholder={"ID"}/>
<TextInput
style={styles.textForm}
placeholder={"Password"}/>
</View>
<View style={styles.buttonArea}>
<TouchableOpacity
style={styles.button}
onPress={this._doLogin.bind(this)}>
<Text style={styles.buttonTitle}>Login</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingLeft: wp('10%'),
paddingRight: wp('10%'),
justifyContent: 'center',
},
titleArea: {
width: '100%',
padding: wp('10%'),
alignItems: 'center',
},
title: {
fontSize: wp('10%'),
},
formArea: {
width: '100%',
paddingBottom: wp('10%'),
},
textForm: {
borderWidth: 0.5,
borderColor: '#888',
width: '100%',
height: hp('5%'),
paddingLeft: 5,
paddingRight: 5,
marginBottom: 5,
},
buttonArea: {
width: '100%',
height: hp('5%'),
},
button: {
backgroundColor: "#46c3ad",
width: "100%",
height: "100%",
justifyContent: 'center',
alignItems: 'center',
},
buttonTitle: {
color: 'white',
},
})

Unable to navigate to next screen in React Native

I have created a list of posts and want to pass details of one specfic post to another screen. I want to be able to click on the post and be directed to the post details screen. This is the PostList.js file:
import React, {Component} from 'react';
import {
FlatList,
StyleSheet,
View,
Text,
Modal,
TouchableOpacity,
} from 'react-native';
import Post from './Post';
import Firebase from 'firebase';
import 'firebase/database';
import {firebaseConfig} from './configFirebase';
import PostDetails from './stack/PostDetails';
export default class Posts extends Component {
constructor(props) {
super(props);
!Firebase.apps.length
? Firebase.initializeApp(firebaseConfig.firebase)
: Firebase.app();
this.state = {
postList: [],
navigation: this.props.navigation,
};
}
state = {
loading: false,
currentPost: null,
};
componentDidMount() {
this.getPostData();
}
getPostData = () => {
const ref = Firebase.database().ref('/posts');
ref.on('value', snapshot => {
console.log('DATA RETRIEVED');
const postsObject = snapshot.val();
if (!postsObject) {
return console.warn('No data from firebase');
}
const postsArray = Object.values(postsObject);
this.setState({postList: postsArray});
});
};
render() {
return (
<View style={styles.container}>
<FlatList
keyExtractor={post => post.heading}
data={this.state.postList}
renderItem={({item: post}) => (
<Post
key={post.heading}
heading={post.heading}
description={post.description}
location={post.location}
onPress={() => this.props.navigation.push('PostDetails', {post})}
/>
)}
/>
</View>
);
}
}
export const styles = StyleSheet.create({
container: {
borderWidth: 2,
borderRadius: 5,
backgroundColor: '#2bb76e',
flex: 1,
},
txtInput: {
flex: 1,
margin: 5,
padding: 5,
borderWidth: 2,
fontSize: 20,
borderRadius: 5,
backgroundColor: 'snow',
},
});
I've tried navigation.navigate() and navigation.push() and neither work.
This is the PostDetails Screen I want to navigate to and pass the post info to:
import React from 'react';
import {Text, View} from 'react-native';
export default ({route}) => {
const postInfo = route.params.post;
return (
<View>
<Text>{JSON.stringify(postInfo, null, 2)}</Text>
<Text>{postInfo.heading}</Text>
</View>
);
};
This is my HomeStack file where the screens are kept:
import React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import Posts from '../PostList';
import AddForm from '../AddForm';
import PostDetails from './PostDetails';
const HomeStack = createStackNavigator();
const HomeStackScreen = () => (
<HomeStack.Navigator>
<HomeStack.Screen
name="PostList"
component={Posts}
options={{headerTitle: 'big APPetite'}}
/>
<HomeStack.Screen
name="PostDetails"
component={PostDetails}
options={({route}) => ({heading: route.params.post.heading})}
/>
<HomeStack.Screen name="NewPost" component={AddForm} />
</HomeStack.Navigator>
);
export default HomeStackScreen;
Post.js:
import React, {Component} from 'react';
import {
Image,
Text,
StyleSheet,
View,
TextInput,
FlatList,
TouchableOpacity,
} from 'react-native';
import FavouriteButton from './buttons/FavouriteButton';
import chickenClub from './images/chickenSandwich.jpg';
const Post = ({heading, description, location, username}) => (
<TouchableOpacity style={postStyle.container}>
<View style={(postStyle.container, {alignItems: 'flex-start'})}>
<View style={postStyle.padding}>
<Image style={postStyle.image} source={chickenClub} />
<View style={{backgroundColor: (255, 255, 255, 45), borderRadius: 6}}>
<Text style={postStyle.text}>{heading}</Text>
<Text style={postStyle.text}>{location}</Text>
<Text style={postStyle.text}>{username}*username*</Text>
</View>
</View>
<View
style={{
alignSelf: 'flex-end',
flexDirection: 'column',
backgroundColor: '#2bb76e',
}}>
<Text style={postStyle.paragraph}>{description}</Text>
<View style={{justifyContent: 'flex-start', alignItems: 'flex-end'}}>
<FavouriteButton />
</View>
</View>
</View>
</TouchableOpacity>
);
const postStyle = StyleSheet.create({
container: {
borderWidth: 2,
borderRadius: 5,
backgroundColor: '#2bb76e',
flex: 1,
},
padding: {
padding: 10,
},
heading: {
backgroundColor: (255, 250, 250, 50),
flexDirection: 'column',
},
paragraph: {
alignSelf: 'flex-end',
fontSize: 20,
},
username: {},
image: {
flexDirection: 'row',
height: 150,
width: 150,
},
text: {
fontSize: 25,
padding: 5,
},
});
export default Post;
You are passing onPress to your Post component, however you are not applying that prop to the TouchableOpacity.
Modifying the Post component to include:
const Post = ({heading, description, location, username, onPress}) => (
<TouchableOpacity style={postStyle.container} onPress={onPress}>

Categories

Resources