Why does my screen in react native show that the parameters I passed through my navigation are undefined? - react-native

So in summary I'm trying to pass my 'name' variable from my 'Signup.js' screen to my 'Home.js' by passing parameters to routes through my navigation.navigate() function.
So Here's my Signup.js Screen:
import firebaseConfig from '../firebase';
import {
Pressable,
Text,
TextInput,
View,
ActivityIndicator,
} from 'react-native';
import {useNavigation} from '#react-navigation/native';
import {initializeApp} from 'firebase/app';
import {
getAuth,
createUserWithEmailAndPassword,
onAuthStateChanged,
} from 'firebase/auth';
import React, {useState, useEffect} from 'react';
import styles from './Stylesheets/Signup-Stylesheet';
const Signup = () => {
const navigation = useNavigation();
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const [name, setName] = useState(''); //THIS VARIABLE NEEDS TO GO TO HOME.JS
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
function handleSignUpData() {
console.log(name);
setLoading(prevLoading => !prevLoading);
createUserWithEmailAndPassword(auth, email, password)
.then(userCredential => {
const user = userCredential.user;
})
.catch(error => alert(error.message));
}
useEffect(() => {
onAuthStateChanged(auth, user => {
if (user) {
navigation.navigate('Home', {name: name});
}
});
}, []);
return (
<View style={styles.container}>
<View style={styles.welcome}>
<Text style={styles.welcomeText}>
Hello! Tell me more about yourself:
</Text>
</View>
<View style={styles.form}>
<TextInput
onChangeText={text => setName(text)}
placeholderTextColor={'#3c2a21'}
placeholder="Name"
style={styles.input}
/>
<TextInput
onChangeText={text => setEmail(text)}
placeholderTextColor={'#3c2a21'}
placeholder="Email"
style={styles.input}
/>
<TextInput
onChangeText={text => setPassword(text)}
secureTextEntry
placeholderTextColor={'#3c2a21'}
placeholder="Password"
style={styles.input}
/>
<Pressable onPress={handleSignUpData} style={styles.submit}>
{loading ? (
<ActivityIndicator size="large" color="black" />
) : (
<Text style={styles.submitText}>Submit</Text>
)}
</Pressable>
</View>
</View>
);
};
export default Signup;
And here's my Home.js screen:
import {StyleSheet, Text, View, BackHandler, Alert} from 'react-native';
import React from 'react';
const Home = ({route}) => {
console.log(route.params.name);
At this point in time as long as it logs it to the console it's fine. But I keep getting this error:
cannot read property 'name' of undefined
I've gone through the react navigation docs and I'm still not sure what's wrong with my code. Maybe It's the useEffect() function? So I'd really like some help here!
I've tried to change the parameters to something like:
navigation.navigate('Home', {username: name}) but I still get the same error.

Related

I have a list of around 150 objects and when i map it only around 20 load | React Native

Assume the fetch returns an object of 150 items, of this 150 items only 20 are rendered as components. I've tried FlatList, LargeList and have watched multiple youtube videos and can't seem to get it to work.
I run this on the Expo Dev app, and when I scroll to the bottom of the list, no more load. Only about 20 cards are rendered.
This is what the end of the screen looks like, I try scroll down more and no more load.
Screen shot when scrolling to the bottom:
Screen shot after scrolling to the bottom:
This is the code for my home screen:
import React, { useEffect, useState } from 'react';
import {StyleSheet, ScrollView, Alert, ActivityIndicator} from 'react-native';
import HeaderTabs from '../components/HeaderTabs';
import Screen from '../components/Screen'
import Categories from '../components/Categories'
import SearchBar from '../components/SearchBar'
import ServiceItem from "../components/ServiceItem";
import tailwind from 'tailwind-react-native-classnames';
import { localServices } from '../data/localServices';
import colors from '../configs/colors'
const YELP_API_KEY = "RF2K7bL57gPbve8oBSiX23GYdCVxIl-KedmS-lyEafEZKNIn6DgsN6j88JvHolhiT4LH-VxT2NvDwgzl9yCTW-5REbbu3Cl5vwqCNUtGhnzzScPinQciOvs6PVBtY3Yx";
const HomeScreen = () => {
const [serviceData, setServiceData] = useState(localServices)
const [city, setCity] = useState("San Francisco")
const [activeTab, setActiveTab] = useState("Delivery");
const [loading, setLoading] = useState(false)
const getServicesFromYelp = () => {
const yelpUrl = `https://api.yelp.com/v3/businesses/search?term=Home+Services&location=${city}`;
const apiOptions = {
headers: {
Authorization: `Bearer ${YELP_API_KEY}`,
},
};
setLoading(true)
return fetch(yelpUrl, apiOptions)
.then((res) => res.json())
.then((json) => {
setLoading(false)
if(json.error) return Alert.alert('Sorry', json.error.description);
setServiceData(
json?.businesses?.filter((business) =>
// business.transactions.includes(activeTab.toLowerCase())
business
// city.includes(business.location.city)
)
)
}
);
};
useEffect(() => {
getServicesFromYelp();
}, [city, activeTab]);
return (
<Screen style={tailwind`bg-white flex-1`}>
<HeaderTabs activeTab={activeTab} setActiveTab={setActiveTab} />
<SearchBar setCity={setCity} city={city} />
<ScrollView style={tailwind`flex-1`} showsVerticalScrollIndicator={false}>
<Categories />
{loading && <ActivityIndicator size="large" color={colors.primary} style={tailwind`mt-2 mb-6`} />}
<ServiceItem serviceData={serviceData} />
</ScrollView>
</Screen>
);
}
const styles = StyleSheet.create({})
export default HomeScreen;
This is the code for the individual components:
ServiceItem.js:
import React from 'react';
import { View } from 'react-native';
import ServiceItemCard from "./ServiceItemCard";
const ServiceItem = ({ serviceData }) => {
return (
<View>
{serviceData?.map((item, index) => (
<ServiceItemCard key={index} item={item} />
))}
</View>
);
}
export default ServiceItem;
ServiceItemCard.js:
import React, { useState } from 'react';
import { Image, Text, TouchableOpacity, View, FlatList } from 'react-native';
import tailwind from 'tailwind-react-native-classnames';
import { Entypo } from '#expo/vector-icons';
import { MaterialCommunityIcons } from '#expo/vector-icons';
const ServiceItemCard = ({ item }) => {
const [loved, setLoved] = useState(false)
return (
<View style={tailwind`mx-4 mb-4`}>
<Image
source={{ uri: item.image_url ? item.image_url : null}}
style={tailwind`w-full h-48 rounded-lg`}
/>
<TouchableOpacity style={tailwind`absolute top-2 right-2`} onPress={() => setLoved(e => !e)}>
<Entypo name={`${loved ? 'heart' : 'heart-outlined'}`} size={28} color="#fff" />
</TouchableOpacity>
<View style={tailwind`flex-row items-center mt-1`}>
<View style={tailwind`flex-grow`}>
<Text style={tailwind`font-bold text-lg`} numberOfLines={1}>{item.name}</Text>
<View style={tailwind`flex-row items-center`}>
<MaterialCommunityIcons name="clock-time-four" size={13} color="#06C167" />
<Text style={tailwind`text-xs text-gray-700`}> 20-30 • min • {item.price}</Text>
</View>
</View>
<View style={tailwind`w-8 h-8 justify-center items-center bg-gray-100 rounded-full`}>
<Text style={tailwind`text-gray-600 text-xs`}>{item.rating}</Text>
</View>
</View>
</View>
)
}
export default ServiceItemCard;
I tried using FlatList, LargeList and messing around with infinite scrolling

Pass data between components in React Native

I've been reading the documentation and searching code here, but I can't find anything that helps me.
The idea is to change the email and password values when onChange is triggered so then it will be possible to retrieve that same data from App.js but I can't find any simple example of how this works using functional components.
After reading docs/inet seems like ReactNative has been changing a lot.
Here is my Form.js component:
import React, {useState} from 'react';
import {View, Text, TextInput} from 'react-native';
import styles from './styles';
const Form = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<View styles={styles.container}>
<Text style={styles.inputLabel}>Email</Text>
<TextInput
placeholder="Email"
onChangeText={email => setEmail(email)}
style={styles.input}
value={email}
/>
<Text style={styles.inputLabel}>Password</Text>
<TextInput
secureTextEntry={true}
placeholder="Password"
onChangeText={password => setPassword(password)}
style={styles.input}
value={password}
/>
</View>
);
};
export default Form;
And my App.js component
import React from 'react';
import {View, Button} from 'react-native';
import styles from './styles';
import Form from './Form';
import Greeting from './Greeting';
import Terms from './Terms';
const handleButton = data => {
console.log(data);
};
const App = () => {
return (
<View style={styles.container}>
<Greeting />
<Form />
<Terms />
<View style={{marginTop: 35}}>
<Button
onPress={() => handleButton(Form['email'])}
style={styles.confirmBtn}
title="Crear cuenta"
/>
</View>
</View>
);
};
export default App;
Since Form.js is the child component of the App.js you need to initialise the state in App.js and pass the setState function to Form.js like below
App.js
import React, {useState} from 'react';
import {View, Button} from 'react-native';
import styles from './styles';
import Form from './Form';
import Greeting from './Greeting';
import Terms from './Terms';
const App = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleButton = data => {
console.log(email);
};
return (
<View style={styles.container}>
<Greeting />
<Form setEmail={(e)=>setEmail(e)} setPassword={(p)=>setPassword(p)} />
<Terms />
<View style={{marginTop: 35}}>
<Button
onPress={() => handleButton()}
style={styles.confirmBtn}
title="Crear cuenta"
/>
</View>
</View>
);
};
export default App;
Form.js
import React, {useState} from 'react';
import {View, Text, TextInput} from 'react-native';
import styles from './styles';
const Form = ({setEmail,setPassword}) => {
return (
<View styles={styles.container}>
<Text style={styles.inputLabel}>Email</Text>
<TextInput
placeholder="Email"
onChangeText={email => setEmail(email)}
style={styles.input}
value={email}
/>
<Text style={styles.inputLabel}>Password</Text>
<TextInput
secureTextEntry={true}
placeholder="Password"
onChangeText={password => setPassword(password)}
style={styles.input}
value={password}
/>
</View>
);
};
export default Form;

React Native Render Error undefined is not an object (evaluating '_useContext.register')

My useContext look like is work but when i chnage screen to SignUpScreen it give me Error like this
Render Error undefined is not an object (evaluating
'_useContext.refister')
here is my SignUpScreen.js
import React, { useContext, useState } from 'react';
import { View, Text, Button, StyleSheet, TouchableOpacity, Image } from 'react-native';
import FormInput from '../components/FormInput';
import FormButton from '../components/FormButton';
import FormRedButton from '../components/FormRedButton'
import { firebase } from '../firebase/Firebase'
import { AuthContext, AuthProvider } from "../database/AuthProvider";
const SignupScreen = ({ navigation }) => {
const [email, setEmail] = useState();
const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const {register} = useContext(AuthContext);
return (
<View style={styles.container}>
{/* <Image
source={require('../Logo/Mahan2.jpg')}
style={styles.logo}
/> */}
<Text style={styles.text}>Create an account</Text>
{/* UserName */}
<FormInput
lableValue={email}
onChangeText={(userEmail) => setEmail(userEmail)}
placeholderText="Email"
iconType="user"
autoCapitalize="none"
autoCorrect={false}
/>
{/* Password */}
<FormInput
lableValue={password}
onChangeText={(userPassword) => setPassword(userPassword)}
placeholderText="Password"
iconType="lock"
secureTextEntry={true}
/>
{/* Confirm Password */}
<FormInput
lableValue={confirmPassword}
onChangeText={(userConfirmPassword) => setConfirmPassword(userConfirmPassword)}
placeholderText="Confirm Password"
iconType="lock"
secureTextEntry={true}
/>
<FormButton
buttonTitle="Sign Up"
onPress={() => alert("Sing Up")}
/>
<FormRedButton
buttonTitle="Back"
onPress={() => navigation.navigate('Login')}
/>
</View>
)
}
export default SignupScreen;
const styles = StyleSheet.create({
......
})
And this is my AuthProvider.js
import React, { createContext, useState } from "react";
import auth from '#react-native-firebase/auth';
export const AuthContext = createContext();
export const AuthProvider = ({children}) => {
const [user, setUser] = useState(null);
return(
<AuthContext.Provider
value={{
user,
setUser,
login: async (email, password) => {
try{
await auth().signInWithEmailAndPassword(email, password);
} catch(e) {
console.log(e);
}
},
register: async (email, password) => {
try{
await auth().createUserWithEmailAndPassword(email, password);
} catch(e) {
console.log(e);
}
},
logout: async () => {
try{
await auth().signOut()
} catch(e) {
console.log(e);
}
}
}}
>
{children}
</AuthContext.Provider>
)
}
Here is my ScreenShot Error
enter image description here
I have no Idea how to solve it
You forgot to wrap App component , check this example :
https://snack.expo.dev/AVVpx0PJ7

How do i make so the TextInput clears after submit in react native

I have a TextInput in my code that doesn't clear itself after submit and i have no idea on why it does that or how to solve it. I've looked at other posts that has this kinda issue? but none works or i don't really know where to place the code to make it clear itself after submiting.
Code
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
} from 'react-native';
export default function AddList({ submitHandler }) {
const [text, setText] = useState('');
const changeHandler = (val) => {
setText(val);
}
return(
<View style={styles.container}>
<View style={styles.wrapper}>
<TextInput
style={styles.input}
placeholder='text'
onChangeText={changeHandler}
/>
<Button onPress={() => submitHandler(text)} title='ADD' color='#333' />
</View>
</View>
);
}
Simply create a new function after useState as below:
const onSubmit = useCallback(() => {
if (submitHandler) submitHandler(text)
setText("")
}, [text])
and modify textinput and button as below:
<TextInput
style={styles.input}
placeholder='What Tododay?'
onChangeText={changeHandler}
value={text}
/>
<Button
onPress={onSubmit}
title='ADD TO LIST'
color='#333'
/>
Do not forget to import useCallback from react.
I hope it help you.

React Native Modal CallBack - Passing Props to Parent

I am using React Native Modal and am having difficulty passing back the props from the Modal to the class that called the Modal.
I have tried with the onRequestClose() and onPress() and setting a prop for callback data googlePlacesPassedBackLocation but no success. I am trying to retrieve pastLocations from GooglePlaces. I can see in GooglePlaces that the location is being generated correctly. I am using the useState hook in both the Modal class and the GooglePlaces class.
I have read that this is a difficult thing to do as react doesn't really support it. Is it possible at all?
import {StyleSheet, View, Modal, TouchableOpacity, Text, TouchableHighlight, Button } from 'react-native';
Parent Component:
const RegisterLocationScreen = ({navigation}) => {
var [pastLocations, setPastLocations] = useState([]);
var [pastModalVisible, setModalPastVisible] = useState(false);
const closeModal = (timeFrame) => {
setModalPastVisible(false);
};
const openGooglePastModal = () => {
setModalPastVisible(true)
};
return (
<Modal visible={pastModalVisible} animationType={'slide'} onRequestClose={() => closeModal(pastLocations)}>
<View style={styles.modalContainer}>
<SafeAreaView style = {styles.safeAreaViewStyle} forceInset={{top: 'always'}}>
<GooglePlaces timePeriod="Past" googlePlacesPassedBackLocation={googlePlacesPassedBackLocation} />
<TouchableOpacity style = {styles.buttonContainer} onPress={()=> closeModal('Past')}>
<Text style={styles.buttonText} >
Close Modal
</Text>
</TouchableOpacity>
</SafeAreaView>
</View>
</Modal>
<TouchableOpacity style = {styles.buttonModal} onPress={() => openGooglePastModal()} >
<Text style={styles.buttonModalText} >
Past Locations
</Text>
</TouchableOpacity>
Child Component:
import React, {useState} from 'react';
import {StyleSheet } from 'react-native'
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
const API_KEY = '123omittedforsecurity';
const GooglePlaces = ({timePeriod}) => {
var [pastLocations, setPastLocations] = useState([]);
const updateLocationArray = (data, details) =>{
setPastLocations([
...pastLocations,
details.geometry.location
]);
};
return (
<GooglePlacesAutocomplete
placeholder={timePeriod}
onPress={(data, details) => {
updateLocationArray(data, details);
}}
..../>