Advice need for React Navigation auth flow structure - firebase

Trying out react navigation v5 so I created a login register form that brings the user to the dashboard if he's logged in before using AsyncStorage. It works fine but I would like to know how to improve on the structure of code. Currently, I put all the components in a stack navigator, but things might get messy if I were to add more screens. Also, I would be switching to hooks but am confused if and how I should apply useContext useMemo useEffect
App.js file
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Login from './components/login';
import Signup from './components/signup';
import Dashboard from './components/dashboard';
import AuthLoading from './components/authLoading'
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator
initialRouteName="AuthLoading"
screenOptions={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#3740FE',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}>
<Stack.Screen
name="AuthLoading"
component={AuthLoading}
options={
{title: 'AuthLoading'},
{headerLeft:null}
}/>
<Stack.Screen
name="Signup"
component={Signup}
options={{ title: 'Signup' }}
/>
<Stack.Screen
name="Login"
component={Login}
options={
{ title: 'Login' },
{ headerLeft: null }
}
/>
<Stack.Screen
name="Dashboard"
component={Dashboard}
options={
{ title: 'Dashboard' },
{ headerLeft: null }
}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
authLoading.js file
import React from 'react';
import { ActivityIndicator, StatusBar, StyleSheet, View, Text } from 'react-native';
import {AsyncStorage} from 'react-native'
export default class AuthLoadingScreen extends React.Component {
constructor(props) {
super(props);
this.checkUserToken();
}
async checkUserToken() {
const isLoggedIn = await AsyncStorage.getItem('isLoggedIn');
console.log(isLoggedIn)
// If User Token
if (isLoggedIn === '1') {
//AsyncStorage.setItem(isLoggedIn);
this.props.navigation.navigate('Dashboard');
}
else {
this.props.navigation.navigate('Login');
}
}
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>Checking Authentication</Text>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
// Styles
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#CA3433',
justifyContent: 'center',
alignItems: 'center',
},
text: {
justifyContent: 'center',
color: '#fff',
fontSize: 18,
fontWeight: '500',
},
});
signup.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
export default class Signup extends Component {
constructor() {
super();
this.state = {
displayName: '',
email: '',
password: '',
isLoading: false
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
registerUser = () => {
if (this.state.email === '' && this.state.password === '') {
Alert.alert('Enter details to signup!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
res.user.updateProfile({
displayName: this.state.displayName
})
console.log('User registered successfully!')
this.setState({
isLoading: false,
displayName: '',
email: '',
password: ''
})
this.props.navigation.navigate('Login')
})
.catch(error => this.setState({
isLoading: false,
errorMessage: error.message
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Name"
value={this.state.displayName}
onChangeText={(val) => this.updateInputVal(val, 'displayName')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signup"
onPress={() => this.registerUser()}
/>
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Login')}>
Already Registered? Click here to login
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});
login.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
import {AsyncStorage} from 'react-native';
export default class Login extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
isLoading: false,
errorMessage: ''
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
/**
*
*/
userLogin = () => {
if (this.state.email === '' && this.state.password === '') {
this.setState({
errorMessage: "Enter details to sign in"
})
//Alert.alert('Enter details to signin!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
console.log(res)
console.log('User logged-in successfully!')
this.setState({
isLoading: false,
email: '',
password: ''
})
AsyncStorage.setItem('isLoggedIn', '1')
this.props.navigation.navigate('Dashboard')
})
.catch(error => this.setState({
errorMessage: 'Wrong email/password',
isLoading: false
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signin"
onPress={() => this.userLogin()}
/>
{/* style this */}
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Signup')}>
Don't have account? Click here to signup
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});
dashboard.js file
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, Button, Alert, ActivityIndicator } from 'react-native';
import firebase from '../database/firebase';
import {AsyncStorage} from 'react-native';
export default class Login extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
isLoading: false,
errorMessage: ''
}
}
updateInputVal = (val, prop) => {
const state = this.state;
state[prop] = val;
this.setState(state);
}
/**
*
*/
userLogin = () => {
if (this.state.email === '' && this.state.password === '') {
this.setState({
errorMessage: "Enter details to sign in"
})
//Alert.alert('Enter details to signin!')
} else {
this.setState({
isLoading: true,
})
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then((res) => {
console.log(res)
console.log('User logged-in successfully!')
this.setState({
isLoading: false,
email: '',
password: ''
})
AsyncStorage.setItem('isLoggedIn', '1')
this.props.navigation.navigate('Dashboard')
})
.catch(error => this.setState({
errorMessage: 'Wrong email/password',
isLoading: false
}))
}
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E" />
</View>
)
}
return (
<View style={styles.container}>
<TextInput
style={styles.inputStyle}
placeholder="Email"
value={this.state.email}
onChangeText={(val) => this.updateInputVal(val, 'email')}
/>
<TextInput
style={styles.inputStyle}
placeholder="Password"
value={this.state.password}
onChangeText={(val) => this.updateInputVal(val, 'password')}
maxLength={15}
secureTextEntry={true}
/>
<Button
color="#3740FE"
title="Signin"
onPress={() => this.userLogin()}
/>
{/* style this */}
<Text>{this.state.errorMessage}</Text>
<Text
style={styles.loginText}
onPress={() => this.props.navigation.navigate('Signup')}>
Don't have account? Click here to signup
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
flexDirection: "column",
justifyContent: "center",
padding: 35,
backgroundColor: '#fff'
},
inputStyle: {
width: '100%',
marginBottom: 15,
paddingBottom: 15,
alignSelf: "center",
borderColor: "#ccc",
borderBottomWidth: 1
},
loginText: {
color: '#3740FE',
marginTop: 25,
textAlign: 'center'
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff'
}
});

React-Navigation provided help regarding the auth flow on their official site. Just follow the below link
https://reactnavigation.org/docs/auth-flow/
Note: You can follow this article for authentication flow using hooks and react-navigation 5
https://dev.to/embeddednature/create-an-authorization-flow-with-react-navigation-5-x-2pkh

Related

TypeError: undefined is not an object (evaluating '_firebase.database.ref')

I get this error :
"TypeError: undefined is not an object (evaluating '_firebase.database.ref')"
I don't understand why this error is happening.
This is the code:
import { useNavigation } from '#react-navigation/core'
import React, { useState } from 'react'
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import { auth, database } from '../firebase'
const HomeScreen = () => {
const navigation = useNavigation()
const [led1Status, setLed1Status] = useState("1")
const handleSignOut = () => {
auth
.signOut()
.then(() => {
navigation.replace("Login")
})
.catch(error => alert(error.message))
}
const handleLed1Toggle = () => {
const firebaseRef = database.ref().child("Led1Status")
if (led1Status === "1") {
firebaseRef.set("0")
setLed1Status("0")
} else {
firebaseRef.set("1")
setLed1Status("1")
}
}
return (
<><View style={styles.container}>
<Text>Email: {auth.currentUser?.email}</Text>
<TouchableOpacity
onPress={handleSignOut}
style={styles.button}
>
<Text style={styles.buttonText}>Sign out</Text>
</TouchableOpacity>
</View>
<View style={styles.bruhst}>
<TouchableOpacity
onPress={handleLed1Toggle}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Say it</Text>
</TouchableOpacity>
</View></>
)
}
export default HomeScreen
const styles = StyleSheet.create({
bruhst: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
marginTop: 30,
marginLeft: 20,
},
button: {
backgroundColor: '#F2ACB9',
width: '50%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
marginTop: 15,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutline: {
backgroundColor: 'white',
},
buttonOutlineText: {
color: '#F2ACB9',
fontWeight:'700',
fontSize: 16,
},
})
I am working on a mobile app with a button. im trying to make the button 'Say it' when pressed to change the value of the key from the realtime database from firebase from a 0 to a 1. the key name on the realtie database is Led1Status.

borderTopColor not working for React-Native "View"

I am developing my first React Native app and I am trying to design a footer for the main screen. To do that I created a view and placed it under the scrollView. Then I tried making a borderTopColor to separate the footer from the rest of the page but it did not work.
home.js
import { StatusBar } from 'expo-status-bar'
import { StyleSheet, Text, View, FlatList, Image, Button, Pressable, ScrollView } from 'react-native';
import React, {useState, useEffect} from 'react'
import { TextInput } from 'react-native-gesture-handler';
import AsyncStorage from '#react-native-async-storage/async-storage';
import { FontAwesomeIcon } from '#fortawesome/react-native-fontawesome';
import { faUser } from '#fortawesome/free-regular-svg-icons';
import { faAlignJustify, faUser as solidUser} from '#fortawesome/free-solid-svg-icons'
import { faComments as solidComment } from '#fortawesome/free-solid-svg-icons';
import { faComments } from '#fortawesome/free-regular-svg-icons';
export default function Home(props) {
const [ current, setCurrent ] = useState("profile")
const [ user, setUser ] = useState("")
const curr = (cur) => {
setCurrent(cur)
}
const getData = async () => {
try {
const value = await AsyncStorage.getItem('#userauthkey')
if (value !== null) {
return value
} else {
return false
}
} catch (e) {
console.log(e)
}
}
useEffect(() => {
const ch = async () => {
const c = await getData();
if (c) {
setUser(c)
}
};
ch();
}, []);
const gprof = (user) => {
fetch(`http://192.168.5.223:8000/home/checkprofile/`,{
method: 'POST',
headers: {
"Content-Type": 'application/json',
},
body: JSON.stringify({'user':user}),
} )
.then( res => res.json())
.then( res => {
console.log(res.profile)
console.log(res.sets)
if (res.sets === false){
props.navigation.navigate('Profile')
}
})
.catch( error => console.log(error))
}
const logout = async () => {
try {
await AsyncStorage.removeItem('#userauthkey')
props.navigation.navigate('Login')
} catch(e){
console.log(e)
}
}
if(current === "profile"){
return (
<View style={styles.container}>
<ScrollView style={styles.scroll} >
<Text> profile {user} </Text>
<Pressable onPress={ () => logout()}>
<Text>Logout</Text>
</Pressable>
</ScrollView>
<View style={styles.footer}>
<Pressable onPress={() => curr('messanger')}>
<View style={{ borderWidth: 2, borderStyle: 'solid', borderColor: "white", borderRadius: 20, padding: 3, }}>
<FontAwesomeIcon icon={faComments} style={{color: 'white',}} size={25} />
</View>
</Pressable>
<Pressable onPress={() => curr('profile')}>
<View style={{ borderWidth: 2, borderStyle: 'solid', borderColor: "white", backgroundColor: 'white', borderRadius: 20, padding: 3, }}>
<FontAwesomeIcon icon={solidUser} style={{color: 'black', alignContent:"center", } } size={25} />
</View>
</Pressable>
</View>
<StatusBar style="auto"/>
</View>
)
} else if(current === "posts"){
return (
<View style={styles.container}>
<ScrollView style={styles.scroll} >
<Text> posts {user} </Text>
</ScrollView>
<View style={styles.footer}>
</View>
<StatusBar style="auto"/>
</View>
)
} else if (current === "messanger"){
return (
<View style={styles.container}>
<ScrollView style={styles.scroll} >
<Text> messanger {user} </Text>
</ScrollView>
<View style={styles.footer}>
<Pressable onPress={() => curr('messanger')}>
<View style={{ borderWidth: 2, borderStyle: 'solid', borderColor: "white", backgroundColor:"white", borderRadius: 20, padding: 3}}>
<FontAwesomeIcon icon={solidComment} style={{color: 'black',}} size={25} />
</View>
</Pressable>
<Pressable onPress={() => curr('profile')}>
<View style={{ borderWidth: 2, borderStyle: 'solid', borderColor: "white", borderRadius: 20, padding: 3}}>
<FontAwesomeIcon icon={faUser} style={{color: 'white', borderStyle: 'solid', borderColor: "white", borderRadius: 20}} size={25} />
</View>
</Pressable>
</View>
<StatusBar style="auto"/>
</View>
)
}
}
Home.navigationOptions = screenProps => ({
headerLeft: () => null,
gestureEnabled: false,
headerStyle: {
backgroundColor: 'black'
},
headerTintColor: 'white',
})
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'black',
},
scroll: {
backgroundColor:'#'
},
footer: {
backgroundColor: 'black',
borderTopColor: 'dark-gray',
borderTopWidth: .5 ,
borderStyle: 'solid',
padding:50,
paddingTop:18,
paddingLeft: 18,
paddingRight: 18,
flexDirection: 'row',
alignContent: "space-between",
alignItems: "space-between",
justifyContent: "space-between",
},
label: {
fontSize: 24,
color: "white",
padding: 10,
},
input: {
fontSize: 24,
backgroundColor: "white",
padding: 10,
margin: 10,
borderRadius: 5,
},
});
How can I solve the issue?
dark-gray is not a recognized color keyword in React Native. You may be thinking of darkgray. You can find the full list of supported color keywords here: https://reactnative.dev/docs/colors#color-keywords

Could anyone help me to write code to upload image to the firestore database with url below is my code to upload image with form

I couldn't find a way to upload image to the firestore database with url while I am submitting the I am getting the file path like file:///data/user/0/com.kk/cache/rn_image_picker_lib_temp_6e973dbe-ab8f, but I need to get file path with url in firestore. Could anyone help with this?. Below is my code to upload image with form.
import React, { useState } from "react";
import { View,StyleSheet,Text, ScrollView, Pressable, Image, TextInput } from 'react-native';
import { Button } from "react-native-elements";
import {firebase} from '#react-native-firebase/firestore';
import { launchImageLibrary } from "react-native-image-picker";
export default function Test(){
const [username,setusername] = useState('');
const [email,setemail] = useState('');
const[imageURI,setImageURI] = useState(null);
const handleOpenLibrary = async () => {
let options = {
mediaType: "photo",
};
const imageData = await launchImageLibrary(options);
setImageURI(imageData.assets[0].uri);
};
function create(){
firebase.firestore()
.collection('Actors')
.add({
name: username,
email: email,
image: {uri:imageURI},
}).then(() => {
console.log("data submitted");
}).catch((error)=> {
console.log(error);
});;
} return (
<View style={styles.body}>
<View style={styles.row}>
<TextInput
style={{backgroundColor:'white'}}
value={username}
onChangeText= {(username) => {setusername(username)}}
placeholder="Enter name"/>
</View>
<View style={styles.row}>
<TextInput
style={{backgroundColor:'white'}}
value={email}
onChangeText= {(email) => {setemail(email)}}
placeholder="Enter email"/>
</View>
<View style={styles.imageContainer}>
<Image
source={{uri:imageURI}}
style={styles.imageBox}
resizeMode='contain'
/>
</View>
<Button
title="submit"
onPress={create}/>
<Button title="pick" onPress={handleOpenLibrary}/>
</View>
)}
const styles = StyleSheet.create({
body: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'flex-start',
},
text: {
fontSize: 40,
margin: 10,
},
row: {
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent:'space-between',
},
footer: {
position: 'absolute',
flex:0.1,
left: 0,
right: 0,
bottom: -10,
flexDirection:'row',
height:50,
alignItems:'center',
justifyContent:'center',
borderRadius:10,
},
footerText: {
color:'white',
fontWeight:'bold',
alignItems:'center',
fontSize:18,
},
imageContainer: {
marginVertical: 20,
borderWidth: 5,
borderColor: '#ff5555'
},
imageBox: {
width: 256,
height: 256
}
});

how to stay user logged in using react native firebase but not working

Hey this me and i have already written the code to stay user logged IN forever but it doesn't and also it is not throwing any kind of error and whenever i refresh my expo server or whenever i close my app and reopen it shows me login screen again
import React, { useState } from "react";
import {
View,
Text,
TextInput,
Button,
StyleSheet,
Pressable,
TouchableOpacity,
Alert,
} from "react-native";
import { firebase } from "../../firebase";
import { Formik } from "formik";
import * as Yup from "yup";
import Validator from "email-validator";
const LoginForm = ({ navigation }) => {
const LoginFormSchema = Yup.object().shape({
email: Yup.string().email().required("An email is required"),
password: Yup.string()
.required()
.min(6, "Your password has to have at least 6 characters"),
});
const onLogin = async (email, password) => {
try {
await firebase.auth().signInWithEmailAndPassword(email, password);
console.log("Firebase Login Successfully" + email, password);
} catch (error) {
Alert.alert(error.message);
}
};
return (
<View style={styles.wrapper}>
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values) => {
onLogin(values.email, values.password);
}}
validationSchema={LoginFormSchema}
validateOnMount={true}
>
{({ handleChange, handleBlur, handleSubmit, values, isValid }) => (
<>
<View
style={[
styles.inputField,
{
borderColor:
values.email.length < 1 || Validator.validate(values.email)
? "#ccc"
: "red",
},
]}
>
<TextInput
placeholder="Phone Number, username or email"
autoCapitalize="none"
keyboardType="email-address"
textContentType="emailAddress"
autoFocus={true}
onChangeText={handleChange("email")}
onBlur={handleBlur("email")}
value={values.email}
/>
</View>
<View
style={[
styles.inputField,
{
borderColor:
1 > values.password.length || values.password.length >= 6
? "#ccc"
: "red",
},
]}
>
<TextInput
placeholder="Password"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry={true}
textContentType="password"
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
value={values.password}
/>
</View>
<View style={{ alignItems: "flex-end", marginBottom: 30 }}>
{/* <Text style={{ color: "#68B0F5" }}>Forgot Password?</Text> */}
</View>
<View style={{ justifyContent: "center", alignItems: "center" }}>
<Pressable
titleSize={20}
style={styles.button(isValid)}
disabled={!isValid}
onPress={handleSubmit}
>
<Text style={styles.buttonText}>Log In</Text>
</Pressable>
</View>
<View style={styles.signupContainer}>
<Text>Don't have an account?</Text>
<TouchableOpacity onPress={() => navigation.push("SignupScreen")}>
<Text style={{ color: "#68B0F5" }}>Sign Up</Text>
</TouchableOpacity>
</View>
</>
)}
</Formik>
</View>
);
};
const styles = StyleSheet.create({
wrapper: {
marginTop: 80,
},
inputField: {
borderRadius: 4,
padding: 12,
backgroundColor: "#FAFAFA",
marginBottom: 10,
borderWidth: 1,
},
button: (isValid) => ({
backgroundColor: isValid ? "#DC143C" : "#f56991",
alignItems: "center",
justifyContent: "center",
minHeight: 42,
borderRadius: 50,
width: "60%",
}),
buttonText: {
color: "white",
fontWeight: "600",
fontSize: 20,
},
signupContainer: {
flexDirection: "row",
width: "100%",
justifyContent: "center",
marginTop: 50,
},
});
export default LoginForm;
and i am creating a Instagram clone with the help of this tutorial : https://www.youtube.com/watch?v=UbixZZDjrdU&t=390s

TypeError: navigation.getParam is not a function - react native

This is the error I get-->
I have a HomeFeed.js where I list all my articles and when you click on each article you get taken to the Content.js where you can see the article details/content.
In the HomeFeed.js, when you press on the article this happens-->
..........................................................................................................................................................................................................................................................................................................................................................................................
onPress={() => {
this.props.navigation.navigate("Content", {
articlekey: `${JSON.stringify(item.key)}`,
});
}}
..........................................................................................................................................................................................................................................................................................................................................................................................
In my Content.js, I have the below:
import React, { Component } from "react";
import { StyleSheet, ScrollView, ActivityIndicator, View } from "react-native";
import { Text, Card } from "react-native-elements";
import firebase from "../../firebase";
class Content extends Component {
static navigationOptions = {
title: "Content",
};
constructor() {
super();
this.state = {
isLoading: true,
article: {},
key: "",
};
}
componentDidMount() {
const { navigation } = this.props;
const ref = firebase
.firestore()
.collection("articles")
.doc(JSON.parse(navigation.getParam("articlekey")));
ref.get().then((doc) => {
if (doc.exists) {
this.setState({
article: doc.data(),
key: doc.id,
isLoading: false,
});
} else {
console.log("No such document!");
}
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.activity}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
}
return (
<ScrollView>
<Card style={styles.container}>
<View style={styles.subContainer}>
<View>
<Text h3>{this.state.article.title}</Text>
</View>
<View>
<Text h5>{this.state.article.content}</Text>
</View>
</View>
</Card>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
subContainer: {
flex: 1,
paddingBottom: 20,
borderBottomWidth: 2,
borderBottomColor: "#CCCCCC",
},
activity: {
position: "absolute",
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: "center",
justifyContent: "center",
},
detailButton: {
marginTop: 10,
},
});
export default Content;
The problem is with your get method of parameters. With react-navigation version 5.X or upper, you need to get params with route.
SOLUTION
Change componentDidMount( ) like this
componentDidMount() {
// const { navigation } = this.props; remove this
const { articlekey } = this.props.route.params; //add this
const ref = firebase
.firestore()
.collection("articles")
.doc(JSON.parse(articlekey));
ref.get().then((doc) => {
if (doc.exists) {
this.setState({
article: doc.data(),
key: doc.id,
isLoading: false,
});
} else {
console.log("No such document!");
}
});
}

Resources