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}>
Related
I'm having a problem getting my React Navigation to actually transition screens. I've used it successfully before and I cannot figure out what my problem is this time. I click my button and no transition happens. I think it might be a problem with the inline onPress not running....does it have to be in Main Button? Or does the inline code on App.js override anything in MainButton.js.
Also...NarScreen is the screen I'm trying to get to.
FILE 1: App.js
import 'react-native-gesture-handler';
import React from 'react';
import { View, Text, StyleSheet, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { color } from 'react-native-reanimated';
import MainButton from './components/MainButton';
import NarScreen from './screens/NarScreen.js'
function HomeScreen({ navigation }) {
return(
<View style={styles.background}>
<View style={styles.logo}>
<Image source={require('./components/HNS1.png')} style={styles.image} resizeMode='contain' />
</View>
<View style={styles.buttons}>
<MainButton onPress={() => navigation.navigate('Nar')}>NAR Test</MainButton>
<MainButton>Tripoli Test</MainButton>
</View>
</View>
);
}
function Nar({ navigation }) {
return(
<NarScreen />
)
}
const Stack = createStackNavigator();
function App() {
return(
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Nar" component={Nar} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
background: {
backgroundColor: '#00629B',
flex: 1,
},
buttons: {
marginTop: "20%",
marginLeft: 10,
},
image: {
width: '80%',
height: 300,
borderRadius: 20,
},
logo: {
borderRadius: 200,
marginTop: '30%',
alignItems: 'center'
},
});
export default App;
File 2: NarScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
const NarScreen = props => {
return(
<View>
<Text>BigScreen!</Text>
</View>
)
}
export default NarScreen;
FILE 3: MainButton.js
import React from 'react';
import {View, Text, StyleSheet, TouchableOpacity, } from 'react-native';
const MainButton = props => {
return <TouchableOpacity>
<View style={styles.button}>
<Text style={styles.buttonText}>{props.children}</Text>
</View>
</TouchableOpacity>
}
const styles = StyleSheet.create({
button: {
backgroundColor: "#FCD757",
paddingVertical: 30,
paddingHorizontal: 30,
height: 100,
width: 300,
marginTop: "10%",
borderRadius: 10,
marginLeft: '12%',
justifyContent: 'space-between',
},
buttonText: {
color: 'black',
fontSize: 26,
textAlign: 'center',
}
})
export default MainButton;
Inside your MainButton.js file, you are not handling onPress event. Add it to touchable opacity.
const MainButton = props => {
return <TouchableOpacity onPress={props.onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>{props.children}</Text>
</View>
</TouchableOpacity>
}
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.
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator, createAppContainer } from '#react-navigation/stack';
import ShopMens from './ShopMens';
import ShopWomens from './ShopWomens';
const CategoryButton = () => {
return(
<View style={styles.buttonCont}>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('ShopMens')}>
<Text style={styles.title}>SHOP MEN'S</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('ShopWomens')} >
<Text style={styles.title}>SHOP WOMEN'S</Text>
</TouchableOpacity>
</View>
)
}
const styles = StyleSheet.create({
buttonCont: {
flexDirection:'row',
justifyContent: 'space-around',
width: '60%',
marginLeft: 10,
marginBottom: 10
},
title: {
fontWeight:'bold'
}
});
const RootStack = createStackNavigator(
{
CategoryButton: CategoryButton,
ShopMens: ShopMens,
ShopWomens: ShopWomens
},
{
initialRouteName: 'CategoryButton'
}
)
export default createAppContainer(RootStack);
React Native Experts. I need help with the navigation between pages.
I have a Home page with Bottom Navigation with Icon that works perfectly fine.
Then on the same I have 2 TouchableOpacity Button that I need to redirect to another page when I press on it.
I separated those 2 buttons on another component called Category Button, on that component I'm trying to do the Stack navigation to redirect the button to another page, but I have an error saying that stack has already been declared. I don't know how to fix this as I'm following the navigation doc on React Native, and I don't know if I'm doing this right. Can someone help?
UPDATE : I was using react-navigation v4 and v5. I now switch everything to react navigation v4 but my navigation between page ShopMens and ShopWomens is still not working, I don't think I did set my stack in the right way
import React from 'react';
import { StyleSheet, View} from 'react-native';
import Home from './components/Home';
export default function App() {
return (
<View style={styles.container}>
<Home />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
textAlign: "center"
},
header: {
color: "lightgreen",
textAlign: "center",
marginTop: 50,
fontSize: 50,
fontWeight: "bold",
}
});
import React from 'react';
import { StyleSheet, Text, View, Image,TouchableOpacity} from 'react-native';
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import { Icon } from 'react-native-elements';
import Profile from './Profile';
import Cart from './Cart';
import Favourite from './Favourite';
import CategoryButton from './CategoryButton';
const Home = () => {
return(
<View style={styles.container}>
<Text style={styles.header}>GOLDEN SHOE</Text>
<CategoryButton />
<Image style={styles.logo} source={{uri:'https://www.vooberlin.com/media/image/cb/d0/3d/JS36105A-13190-001-JIL-SANDER-LEATHER-LOAFERS-BLACK-2.jpg'}}/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginTop: 2,
},
header: {
color: "lightgreen",
textAlign: "center",
marginTop: 50,
fontSize: 60,
fontWeight: "bold",
},
logo: {
width: 450,
height: 550,
},
});
const TabNavigator = createMaterialBottomTabNavigator(
{
Home: {
screen:Home,
navigationOptions: {
tabBarLabel: 'Home',
activeColor:'#000000',
inactiveColor: 'grey',
barStyle:{backgroundColor: 'white'},
tabBarIcon:() =>(
<View>
<Icon
name={'home'}
size={25}
style={{color:'#ff0000'}}
/>
</View>
)
}
},
Profile: {
screen:Profile,
navigationOptions: {
tabBarLabel: 'Profile',
activeColor:'#000000',
inactiveColor: 'grey',
barStyle:{backgroundColor: 'white'},
tabBarIcon:() =>(
<View>
<Icon
name={'person'}
size={25}
style={{color:'#ff0000'}}
/>
</View>
)
}
},
Favourite: {
screen:Favourite,
navigationOptions: {
tabBarLabel: 'Favourite',
activeColor:'#000000',
inactiveColor: 'grey',
barStyle:{backgroundColor: 'white'},
tabBarIcon:() =>(
<View>
<Icon
name={'favorite-border'}
size={25}
style={{color:'#ff0000'}}
/>
</View>
)
}
},
Cart: {
screen:Cart,
navigationOptions: {
tabBarLabel: 'Cart',
activeColor:'#000000',
inactiveColor: 'grey',
barStyle:{backgroundColor: 'white'},
tabBarIcon:() =>(
<View>
<Icon
name={'shopping-cart'}
size={25}
style={{color:'#ff0000'}}
/>
</View>
)
}
},
}
);
export default createAppContainer(TabNavigator);
I'm doing the navigation between components on my React Native App, and so far everything was working relatively ok until I got stuck with this error.
This is the last component I want to navigate but I don't know why I can't do it, every other I followed the same structure for every component and they work, but this is the only one that doesn't.
import React from 'react';
import {
StyleSheet,
View,
TouchableHighlight,
Button
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
const Icono = (props) => {
return(
<TouchableHighlight
underlayColor={'transparent'}
style={styles.icono}
onPress={() => props.navigation.navigate('Login')}>
<View>
<Icon name="video-call" color="#7796ff" size={35} />
</View>
</TouchableHighlight>
);
}
const styles = StyleSheet.create({
icono: {
paddingRight: 10,
paddingLeft: 10,
paddingTop: 17,
textAlign: 'center',
},
});
export default Icono;
This is the code I'm using to achieve the navigation.
import React, {useState} from 'react';
import {View, StyleSheet} from 'react-native';
import {Text} from 'react-native-paper';
import {TextInput} from 'react-native-paper';
import AsyncStorage from '#react-native-community/async-storage';
import {Button} from 'react-native-paper';
import {createStackNavigator} from '#react-navigation/stack';
const Stack = createStackNavigator();
const LoginScreen = (props) => {
const [userId, setUserId] = useState('');
const [loading, setLoading] = useState(false);
const onLogin = async () => {
setLoading(true);
try {
await AsyncStorage.setItem('userId', userId);
setLoading(false);
props.navigation.navigate('Call');
} catch (err) {
console.log('Error', err);
setLoading(false);
}
};
return (
<View style={styles.root}>
<View style={styles.content}>
<Text style={styles.heading}>Ingresa tu ID</Text>
<TextInput
label="id"
onChangeText={text => setUserId(text)}
mode="outlined"
style={styles.input}
/>
<Button
mode="contained"
onPress={onLogin()}
loading={loading}
style={styles.btn}
contentStyle={styles.btnContent}
disabled={userId.length === 0}>
Conectar al servicio de video
</Button>
<Button
mode="contained"
onPress={props.navigation.navigate('Contacto')}
loading={loading}
style={styles.btn}
contentStyle={styles.btnContent}
disabled={userId.length === 0}>
Salir
</Button>
</View>
</View>
);
}
const styles = StyleSheet.create({
root: {
backgroundColor: '#fff',
flex: 1,
justifyContent: 'center',
},
content: {
paddingHorizontal: 20,
justifyContent: 'center',
},
heading: {
fontSize: 18,
marginBottom: 10,
fontWeight: '600',
},
input: {
height: 60,
marginBottom: 10,
},
btn: {
height: 60,
alignItems: 'stretch',
justifyContent: 'center',
fontSize: 18,
},
btnContent: {
alignItems: 'center',
justifyContent: 'center',
height: 60,
},
});
export default LoginScreen;
This is the code I want to navigate to. It's worth to mention that I'm using react-navigation, and all my components are wrapped in the <NavigationContainer>component, but I don't understand why all the other component the navigation works and this one doesn't allow me to do it.
From your code the is a separate component which is not part of the navigation stack
You can solve this in two ways.
Pass the navigation as a prop from parent which is part of the stack
<Icono navigation={this.props.navigation} />
Use the useNavigation hook inside icono and call it from there.
I have a RN app. Trying to pass fields (in the HEADER) from one page to another (from this "Chat" page TO = "Profile View" page. However, its not working.
I put a Touchable Highlight around it, but not working.
I keep getting Error = cannot find 'first_name'. So I dont think its getting the info INSIDE = render () {.....
You may disregard from 'state' down. Just wanted to show you the page layout.
import React, { Component } from "react";
import {
StyleSheet,
View,
Text,
TouchableHighlight,
Dimensions,
Share,
AlertIOS,
Alert,
TouchableOpacity,
Platform,
KeyboardAvoidingView,
KeyboardSpacer,
StatusBar,
DeviceEventEmitter
} from "react-native";
import { LinearGradient } from 'expo-linear-gradient';
import { GiftedChat } from "react-native-gifted-chat";
import { NavigationActions } from "react-navigation";
import moment from "moment";
import * as firebase from "firebase";
import Email from "../modules/email";
import withPreventDoubleClick from "../components/withPreventDoubleClick";
import CircleImage from "../components/circleImage";
import { Entypo } from "#expo/vector-icons";
import {
ActionSheetProvider,
connectActionSheet
} from "#expo/react-native-action-sheet";
import Modal from "react-native-modal";
const { width, height } = Dimensions.get("window");
const TouchableHighlightEx = withPreventDoubleClick(TouchableHighlight);
import { StackNavigator } from "react-navigation";
#connectActionSheet
class App extends React.Component {
render() {
const first_name = this.props.profile.first_name;
const uid = this.props.user.uid;
const user = this.props.user;
const profile = this.props.profile;
const profileId = this.props.profile.uid;
//const uid = this.props.profile.uid;
//const { id, birthday, first_name, work, imageObj, education } = this.props.navigation.state.params;
return (
<View style={styles.container}>
{Platform.OS === "ios" && (
<Entypo
name="dots-three-vertical"
size={25}
style={{ paddingRight: 7, marginTop: 7 }}
color={"#fff"}
onPress={this._onOpenActionSheet}
/>
)}
{Platform.OS !== "ios" && (
<Entypo
name="dots-three-vertical"
size={25}
style={{ paddingRight: 7, marginTop: 15 }}
color={"#fff"}
onPress={() => this._showModal()}
/>
)}
</View>
);
}
export default class Chat extends Component {
//static navigationOptions = {
static navigationOptions = ({ navigation }) => ({
render() {
const first_name = this.props.profile.first_name;
const uid = this.props.user.uid;
const user = this.props.user;
const profile = this.props.profile;
},
headerTitle: (
<TouchableHighlightEx
underlayColor="transparent"
onPress={() =>
navigation.navigate("ProfileView", {
first_name,
birthday,
id,
uid,
date1,
date2,
date3,
profileUid,
profile: rowData,
user: this.props.navigation.state.params.user
})
}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "center"
}}
>
<CircleImage
size={30}
uri={navigation.state.params.profile.imageObj.img_0}
style={{
width: 32,
height: 32,
resizeMode: "contain",
alignSelf: "center"
}}
/>
<Text style={{ color: "#fff", fontSize: 17, marginLeft: 5 }}>
{navigation.state.params.first_name}
</Text>
</View>
</TouchableHighlightEx>
),
title: navigation.state.params.first_name,
headerTintColor: "#fff",
headerBackTitle: null,
headerRight: (
<ActionSheetProvider>
<App
method={navigation.state.params._showModal}
goBack={navigation.state.params._goBack}
details={navigation.state.params.first_name}
profileId={navigation.state.params.profileUid}
uid={navigation.state.params.user.uid}
user={navigation.state.params.user}
profile={navigation.state.params.profile}
/>
</ActionSheetProvider>
),
headerStyle: {
backgroundColor: "#ff0000",
shadowOpacity: 0,
// iOS
borderBottomWidth: 0,
// Android
elevation: 0
},
});
state = {
messages: [],
user: this.props.navigation.state.params.user,
profile: this.props.navigation.state.params.profile,
modalShow: false,
blockUnblockText: "Block User",
datePlan: null,
isDateLoaded: false,
canLoadEarlier: true,
loadingEarlier: false
};
currentMessage = 20;
messagePerPage = 20;