I have referred official documentation of react native(https://reactnavigation.org/docs/params).In that I observed that they are passing the static data between screens. But I want to pass data taken from user.
If someone knows how to share data then please help. I have taken help of context api also but I failed to pass the data. Any source or material will also be helpful.
Your issue may be related to your input. It seems you are not capturing your inputs into a state variable.
Check this example from ReactNative input:
https://reactnative.dev/docs/0.65/textinput
import React from "react";
import { SafeAreaView, StyleSheet, TextInput } from "react-native";
const Screen1 = () => {
const [text, onChangeText] = React.useState("Hello world");
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={onChangeText}
value={text}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
});
export default Screen1;
Then you could use navigate:
navigation.navigate('Details', {
param1: text,
});
In the other screen you could read the param1 like this:
route.params.param1
Don't forget
Don't forget to pass route as a parameter in fuction( {route) }{ ... }
Checkout this code snippet.
React.useEffect(() => {
if (route.params?.post) {
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Create post"
onPress={() => navigation.navigate('CreatePost')}
/>
<Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
</View>
);
}
function CreatePostScreen({ navigation, route }) {
const [postText, setPostText] = React.useState('');
return (
<>
<TextInput
multiline
placeholder="What's on your mind?"
style={{ height: 200, padding: 10, backgroundColor: 'white' }}
value={postText}
onChangeText={setPostText}
/>
<Button
title="Done"
onPress={() => {
// Pass and merge params back to home screen
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
}}
/>
</>
);
}
to pass a param to a screen
navigation.navigate('screenName', {
paramName: 'valueYouwantToPass',
});
because you mentioned context API, try
Async Storage
import {AsyncStorage} from 'react-native';
or
Device Event Emitter
import { DeviceEventEmitter} from 'react-native';
Related
I have a login page. There, the user enters data and submits to the API. The API gives an answer that there is such a user and gives him an id from the database. I write this id in storage.
Next, the user is taken to the home page.
There is a component that is responsible for getting the username (and indeed all other data)
the essence of the component:
1 The parameter receives an id and forms it into a json request.
2 The parameter sends this request to the API and receives the user's data in the response (if the id matches)
3) return which draws the interface and gives the user data from the API response
Problem:
When changing an account (or re-logging in), it gives a json request error (in fact, the API does not accept an empty request, so it rejects it)
The point of getting an ID is 100%. When the application is updated again, the id turns out to be generated in json and after that I already get data about the user.
How to fix it? In fact, it must first receive the id, and only then the id is sent and the data is received, however, at the first entry into the application, he does not want to receive the ID immediately, but only after a reboot (ctlr + s in VS code)
//LOGIN.js
import React, { Component } from 'react';
import { View, Pressable, Text, TextInput, TouchableOpacity } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import styles from './style';
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email : '',
password : '',
check_textInputChange : false,
secureTextEntry : true,
id : '',
};
}
componentDidMount(){
this._loadInitialState().done();
}
//Сheck that the user with id does not throw out on the authorization screen when exiting the application:
_loadInitialState = async () => {
var id = await AsyncStorage.getItem('id');
if (id !== null) {
this.props.navigation.navigate("HomeScreen")
this.id = id
}
}
InsertRecord () {
var Email = this.state.email;
var Password = this.state.password;
if ((Email.length==0) || (Password.length==0)){
alert("Missing a required field!");
}else{
var APIURL = "http://10.0.2.2:8080/SignIn/login.php";
var headers = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
};
var Data ={
Email: Email,
Password: Password
};
fetch(APIURL,{
method: 'POST',
headers: headers,
body: JSON.stringify(Data)
})
.then((Response)=>Response.json())
.then((Response)=>{
alert(Response[0].Message)
if (Response[0].Message == "Success") {
console.log(Response[0].Message)
// eslint-disable-next-line react/prop-types
AsyncStorage.setItem('id',Response[0].Id);
this.props.navigation.navigate("HomeScreen");
console.log(Response[0].Id);
}
console.log(Data);
})
.catch((error)=>{
console.error("ERROR FOUND" + error);
})
}
}
updateSecureTextEntry(){
this.setState({
...this.state,
secureTextEntry: !this.state.secureTextEntry
});
}
render() {
return (
<View style={styles.viewStyle}>
<View style={styles.action}>
<TextInput
placeholder="Enter Email"
placeholderTextColor="#ff0000"
style={styles.textInput}
onChangeText={email=>this.setState({email})}
/>
</View>
<View style={styles.action}>
<TextInput
placeholder="Enter Pass"
placeholderTextColor="#ff0000"
style={styles.textInput}
secureTextEntry={this.state.secureTextEntry ? true : false}
onChangeText={password=>this.setState({password})}
/>
<TouchableOpacity
onPress={this.updateSecureTextEntry.bind(this)}>
</TouchableOpacity>
</View>
{/* Button */}
<View style={styles.loginButtonSection}>
<Pressable
style={styles.loginButton}
onPress={()=>{
this.InsertRecord()
}}
>
<Text style={styles.text}>Войти</Text>
</Pressable>
</View>
</View>
);
}
}
//INFOSTATUS.js
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, TouchableOpacity, SafeAreaView, FlatList, StyleSheet, Button, View, Text } from 'react-native';
import { useNavigation } from '#react-navigation/native'
import AsyncStorage from '#react-native-async-storage/async-storage';
function InfoStatus() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [idUser, setIdUser] = useState();
//check ID
const idcheck = async () => {
try {
const get = await AsyncStorage.getItem('id')
setIdUser (get)
} catch(e) {
// read error
}
}
//Sending data to api and getting user data
const getNotifications = async () => {
const send = {
id:idUser
}
try {
const response = await fetch('http://10.0.2.2:8080/InfoStatus/InfoStatus.php', {
method: 'POST',
body: JSON.stringify(send),
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
setData(data);
console.log(data);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
idcheck();
getNotifications();
}, []);
//Initialization of received data
const Item = ({ name, middlename,status,number,city }) => (
<View style={StyleInfo.container}>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Dear, </Text>
<Text style={StyleInfo.TextStyleData} key ={name}> {name} {middlename} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Number: </Text>
<Text style={StyleInfo.TextStyleData}key ={number}> № {number} </Text>
<TouchableOpacity
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.ButtonAdress}>Find out the address</Text>
</TouchableOpacity>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Status: </Text>
<Text style={StyleInfo.TextStyleData} key ={status}> {status} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> City: </Text>
<Text style={StyleInfo.TextStyleData} key ={city}> {city} </Text>
</View>
<TouchableOpacity
style={StyleInfo.Button}
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.TextButton}>Get contacts of friends</Text>
</TouchableOpacity>
</View>
);
const renderItem = ({ item }) => (
<Item name={item.name} middlename={item.middlename} status={item.status} yik={item.yik} elections={item.elections} />
);
return (
<SafeAreaView>
{isLoading ? <ActivityIndicator size="large" color="#00ff00"/> : (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
)}
</SafeAreaView>
);
}
const StyleInfo = StyleSheet.create({
container:{
width: 390,
height: 190,
borderWidth: 1,
borderRadius: 2,
marginLeft: 10,
marginBottom: 10,
backgroundColor: '#E9E9E9',
},
container2:{
flexDirection: "row",
},
TextStyle: {
fontFamily: 'Raleway',
fontStyle: 'normal',
fontWeight: 'normal',
fontSize: 18,
marginTop: 5,
marginLeft: 5,
bottom: 10,
top: 10
},
TextStyleData: {
fontSize: 18,
marginTop: 5,
top: 10,
fontWeight: 'bold',
},
ButtonAdress: {
fontSize: 18,
marginTop: 5,
marginLeft: 20,
top: 10,
color: "#ff0000",
},
Button: {
width: 310,
height: 40,
marginTop: 10,
marginLeft: 5,
bottom: 10,
borderWidth: 1,
borderRadius: 2,
top: 10,
alignSelf: 'center',
backgroundColor: "#ff0000",
},
TextButton: {
marginTop: 5,
fontSize: 16,
alignSelf: 'center',
fontWeight: 'bold',
color: 'white',
}
}
)
export {InfoStatus}
PS:
I also caught one thing that when I try to get an id via async / await, then most likely the point is that it does not have time to get the value before rendering. I have run out of ideas, I would like to receive more other suggestions
PSS:
I also know that in fact, even if I passed the value through the navigator, I would pass it to the homescreen. Although my InfoStatus is embedded in the Homescreen and I need to somehow pass this parameter there.
Although in general the question interests me a lot, because I will need this parameter everywhere. Therefore, finding one universal solution would be cool.
I am not 100% sure I understand the question so here a few hints I would give you.
You can pass parameters when navigating like this:
navigation.navigate('somescreen', {
param: 86,
otherParam: 'myBestFriendTheParam',
})
On the next screen you have to then read it from the route.params.
You could use redux to have your user data at hand while the app is open and user logged in? That would give you the data where ever you want basically.
If async/wait does not work why don't you use then-chains like in the rest of your code?
I am using JavaScript + React Native to make an app for my university project. I am using expo to manage my packaging and for viewing the app in the iOS simulator. I am also new to both JavaScript and React Native.
I have been having trouble with implementing a React Native module known as Secure Storage.
https://docs.expo.io/versions/latest/sdk/securestore/
I would like to store user data for the app. Specifically I would like to store a JavaScript object such as:
User{ name:"Bob", age:"20" }
And recall it later.
Having read the documentation, I have made a helper module called "StorageHelper" as seen below:
import * as SecureStore from 'expo-secure-store';
/**
* Stores data
* #param {} key
* #param {*} value
*/
export async function storeObject(key, value)
{
try
{
const jsonValue = JSON.stringify(value);
await SecureStore.setItemAsync(key, jsonValue);
}
catch(e)
{
console.log(e.message);
}
}
/**
* Retrieves data
* #param {} key
*/
export async function getObject(key)
{
let result = await SecureStore.getItemAsync(key);
if (result != null)
{
return result;
}
else
{
alert('No values stored under that key.');
}
On this screen in the app flow, I would like to generate the userObject object and store it in the SecureStorage. This following is
import React from 'react';
import { Text, View, TouchableOpacity, Image } from 'react-native';
import ProjStyleSheet from "../styles/ProjStyleSheet.js";
import * as StorageHelper from "../resources/StorageHelper.js";
const HomeImage = require('../art/HomeImage.png');
const styles = ProjStyleSheet;
function HomeScreen({ navigation }) {
var userData = "Bob"; // instead of the object, I'm just using a simple variable.
StorageHelper.storeObject("userName",userData);
return (
<View style={{
backgroundColor: "#fff",
flexDirection: "column",
justifyContent: "flex-start",
flex:1,}}>
<View style = {{
paddingTop: 100,
paddingBottom: 20,
paddingLeft: 10,
paddingRight: 10,
}}>
<Text style={styles.titleText}>University Money Management App</Text>
</View>
<View style = {{
justifyContent: "space-evenly",
alignItems: "center",
}}>
<Image
style={{width: 250, height: 250, paddingBottom:20}}
source={HomeImage}/>
<TouchableOpacity style={styles.defaultButton}
onPress={() => navigation.navigate('IntroName')}>
<Text style={styles.text}> Get Started </Text>
</TouchableOpacity>
</View>
</View>
);
}
export default HomeScreen;
In the next screen, I am trying to get the data from the secure storage and show it on the screen. This can be seen below:
import React, { useState } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import ProjStyleSheet from "../styles/ProjStyleSheet.js";
import { TextInput } from 'react-native-gesture-handler';
import * as StorageHelper from "../resources/StorageHelper.js";
const styles = ProjStyleSheet;
function IntroName({ navigation })
{
var name = StorageHelper.getObject("userName"); // retrieve the variable here.
return (
<View style={{
flex: 1,
backgroundColor: "#fff",
alignItems: 'center',
justifyContent: "space-around",}}>
<Text style={styles.titleText}>Please Enter Your Name</Text>
<Text> test = {name} </Text> // show the name here
<TextInput
style={{
borderColor: "#000",
borderRadius: 10,
borderWidth: 2,
padding: 20,
fontSize: 20,
width: "75%",
}}
placeholder="Your name here.">
</TextInput>
<TouchableOpacity
style={styles.defaultButton}
onPress={() => navigation.navigate("IntroIncome")}>
<Text style={styles.text}>Next</Text>
</TouchableOpacity>
</View>
);
}
export default IntroName;
Unfortunately, no name appears in the text where I intend it to. I have gone through the Secure Storage documentation and searched through the internet, however I cannot find any answers that can help me. Does anyone have any good ideas on what I am missing to fully implement SecureStorage?
the solution is quite simple. Thanks to the advice of #Tony, I converted all my function components to class components. Within those class components, I wrote an async method which calls the SecureStore method as such: await SecureStore.setItemAsync("user",this.name).
The async method updates the state of the screen, i.e
class Scren extends React.Component
{
constructor()
{
super();
this.state={
data:0,
};
}
async getObject()
{
let result = JSON.parse(await SecureStore.getItemAsync("data");
this.setState({
data: result,
};
}
}
I am trying to familiarize myself with React Native. At the moment I am working on an app but came across an issue when trying to display changes to the individual elements of an array. For example:
function MyApp() {
const [array, setArray] = useState([1,2,3]);
const onPress = () => {
let temp = [3,2,1];
setArray(temp);
}
return(
<View>
<TouchableHighlight onPress={onPress}>
<View>
<Text>{array[0]}</Text>
</View>
</TouchableHighlight>
</View>
);
}
With the above code, I expect '1' to be displayed in the text component and to change to '3' upon being pressed. console.log shows the state being changed but what is being displayed in the text component inside the actual app never updates. I then tried this using individual integer states like so:
const [int, setInt] = useState(0);
const onPress = () => {
setInt(1);
}
Using an integer state such as the one above works totally fine as expected. Can anyone show me what I am doing wrong with my array state? Thank you.
Your code looks perfect and should work without any issue.
Here is the slightly modified example where the first element is generated randomly and is being shown properly in the Text component.
Working Example: Expo Snack
import React, { useState } from 'react';
import { Text, View, StyleSheet, TouchableHighlight } from 'react-native';
import Constants from 'expo-constants';
export default function MyApp() {
const [array, setArray] = useState([1, 2, 3]);
const onPress = () => {
let temp = [Math.floor(Math.random() * 10), 2, 1];
setArray(temp);
};
return (
<View style={styles.container}>
<TouchableHighlight onPress={onPress}>
<View style={styles.btn}>
<Text
style={{ alignSelf: 'center', fontSize: 28, fontWeight: 'bold' }}>
{array[0]}
</Text>
</View>
</TouchableHighlight>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
btn: {
width: 100,
height: 100,
borderColor: 'purple',
borderWidth: 5,
justifyContent: 'center',
},
});
Your code looks to be fine, I tried the below following your code and can see that state and UI getting updated successfully when the button is being clicked.
Could you please check if your event handler function onPress is getting called, and if you are getting any error in the console when you click on it.
function App() {
const [array, setArray] = React.useState([1, 2, 3]);
const handleBtnClick = () => {
const temp = [3, 2, 1];
setArray(temp);
};
return (
<React.Fragment>
<button onClick={handleBtnClick}>Click</button>
{array.map((el) => (
<p>{el}</p>
))}
<hr />
{array[0]}
</React.Fragment>
);
}
I'm studying react native version 5 and I would need a short but working example of two files.js, for example App.js and Receiver.js where:
in App.js you can insert a text through Text Input
in Receiver.js it receives and shows the text inserted once have been passed as state and parameter by the previous page.
Can anyone help me?
App.js
export default class App extends Component {
state = {
username: 'demo'
};
render() {
return (
<Text style={Style.label}>User Name</Text>
<TextInput
style={Style.input}
placeholder="UserName"
onChangeText={(value) => this.setState({username: value})}
value={this.state.username}
/>
<Button
title="LOGIN"
onPress={() => this.props.navigation.navigate("Receiver", {username: this.state.username}) }
/>
);
}
}
Receiver.js
export default class Receiver extends Component {
render() {
const { username} = this.props.route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>User Name: {username}</Text>
</View>
);
}
}
A small suggestion: Read the official document before beginning.✌️
https://reactnavigation.org/docs/params/
I'm trying to create a simple-ish mobile app, but I'm pretty new to this. I've spent some time searching about the errors I'm getting. It seems like a common problem, but they all had the same/similar solutions but the solutions didn't work for me.
What is I'm trying to do? Right now the app is two pages, the home screen (Overview Cards) and the Add Card screen.
There's a button on the Overview Cards that takes you to Add Card.
Add Card allows you to fill out some TextInput boxes and
Add Card should allow you to press the save button and be taken back to the Overview Card screen and see the data you entered in the form.
However, I am getting stuck at Step 3. I am trying to make the Save button navigate the user back to Overview Cards, but there are simply errors instead.
Below is my code, the errors I'm getting, and then what I've tried.
App.js
import React from 'react';
import { StyleSheet, Text, TextInput, View, Button, TouchableOpacity, ShadowPropTypesIOS } from 'react-native';
import AddCard from './components/AddCard.js';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { useNavigation } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={styles.homeContainer}>
<Button title="Add Card" onPress={() => navigation.navigate('Add Card')}/>
{/* <Text value={this.props.inputValFT}/> */}
<Text style={styles.textStyle} >VISA xxxx</Text>
<Text style={styles.textStyle}>MASTERCARD xxxx</Text>
<Text style={styles.textStyle}>AMEX xxxx</Text>
</View>
);
}
function AddCardScreen() {
return (
<View style={styles.addCardContainer}>
<AddCard navigation={this.props.navigation} /> // **HERE**
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview Cards' }} />
<Stack.Screen name="Add Card" component={AddCardScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
// function AddCardButton(){
// return (
// <View style={styles.buttonContainer}>
// <TouchableOpacity>
// <Text style={styles.button}>Add Card</Text>
// </TouchableOpacity>
// </View>
// );
// }
export default App;
const styles = StyleSheet.create({
homeContainer: {
flex: 1,
backgroundColor: '#ef95b1',
alignItems: 'center',
justifyContent: 'flex-start',
},
addCardContainer: {
flex: 1,
backgroundColor: '#28cdf0',
justifyContent: 'flex-start',
},
buttonContainer: {
flexDirection: 'row',
alignSelf: 'flex-end',
marginTop: 15,
},
button: {
flexDirection: 'row',
alignSelf: 'flex-end',
marginTop: 15,
right: 10,
backgroundColor: '#2565ae',
borderWidth: 1,
borderRadius: 12,
color: 'white',
fontSize: 15,
fontWeight: 'bold',
overflow: 'hidden',
padding: 10,
textAlign:'center',
},
textStyle: {
padding: 10,
}
});
Navigation.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import AddCardScreen from './AddCard';
const RootStack = createStackNavigator(
{
Home: HomeScreen,
AddCard: AddCardScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ef95b1',
alignItems: 'center',
justifyContent: 'flex-start',
},
textStyle: {
padding: 10,
}
});
export default createAppContainer(Navigation);
AddCard.js
import React, { Component } from 'react';
import { StyleSheet, View, Text, TextInput, TouchableOpacity } from 'react-native';
import { Input } from 'react-native-elements'
import { ScrollView } from 'react-native-gesture-handler';
// import { loadSettings, saveSettings } from '../storage/settingsStorage';
class AddCardScreen extends Component {
constructor(props) {
super(props);
this.state = {
firstTwo : '',
lastFour : '',
recentAmt : ''
};
this.addFT = this.addFT.bind(this)
this.addLF = this.addLF.bind(this)
this.addRecAmt = this.addRecAmt.bind(this)
}
static navigationOptions = {
title: 'Add Card'
};
addFT(firstTwo) {
this.setState(Object.assign({}, this.state.firstTwo, { firstTwo }));
}
addLF(lastFour) {
this.setState(Object.assign({}, this.state.lastFour, { lastFour }));
}
addRecAmt(recentAmt) {
this.setState(Object.assign({}, this.state.recentAmt, { recentAmt }));
}
// handleSubmit() {
// alert('New card saved. Returning to Home to view addition.');
// navigation.navigate('Home')
// } // firstTwo, lastFour, recentAmt
render() {
const {navigation} = this.props;
return (
<ScrollView>
<View style={styles.inputContainer}>
<Text h1> "Add a new card!" </Text>
<TextInput
style={styles.textInput}
placeholder="First two digits of card"
placeholderTextColor="#000000"
keyboardType={'number-pad'}
maxLength = {2}
onChangeText={this.addFT}
inputValFT={this.state.firstTwo}
/>
<TextInput
style={styles.textInput}
placeholder="Last four digits of card"
placeholderTextColor="#000000"
keyboardType={'number-pad'}
maxLength = {4}
onChangeText={this.addLF}
inputValLF={this.state.lastFour}
/>
<TextInput
style={styles.textInput}
placeholder="Most recent dollar amount"
placeholderTextColor="#000000"
keyboardType={'decimal-pad'}
onChangeText={this.addRecAmt}
inputValRA={this.state.recentAmt}
/>
</View>
<View style={styles.inputContainer}>
<TouchableOpacity
style={styles.saveButton}
onPress={() => navigation.navigate('Home')}> // ** HERE 2 **
<Text style={styles.saveButtonText}>Save</Text>
</TouchableOpacity>
</View>
</ScrollView>
);
}
}
// this.handleSubmit.bind(this)
export default AddCardScreen;
const styles = StyleSheet.create({
inputContainer: {
paddingTop: 15
},
textInput: {
borderColor: '#FFFFFF',
textAlign: 'center',
borderTopWidth: 1,
borderBottomWidth: 1,
height: 50,
fontSize: 17,
paddingLeft: 20,
paddingRight: 20
},
saveButton: {
borderWidth: 1,
borderColor: '#007BFF',
backgroundColor: '#007BFF',
padding: 15,
margin: 5
},
saveButtonText: {
color: '#FFFFFF',
fontSize: 20,
textAlign: 'center'
}
});
The errors I'm getting:
In App.js you can see the ** HERE ** that I put in. When I try to run this, the app loads fine until I click the "Add Card" button. I get this error: undefined is not an object (evaluating 'this.props.navigation').
If I take the navigate={this.props.navigation} part out from App.js, the app loads as it's meant to again, but this time I can click the "Add Card" button and reach the next screen with no issue. I fill out the form (TextInput parts in AddCard.js), but when I click the "Save" button, the app crashes. The error is: TypeError: undefined is not an object (evaluating 'navigation.navigate'). Most likely because of what I'm doing with onPress where it says ** HERE 2 ** in AddCard.js. handleSubmit() is currently commented out, but it used to be inside the onPress.
What I've tried:
Some of the answers I saw were that I need to pass in navigation from the parent to the child and that will make it work. By trying that, I get the errors I mentioned earlier. I also saw that someone mentioned using "withNavigation" or "useNavigation" which was supposed to allow the child to access navigation, but that didn't work for me either. Below are some of the links that I was trying to follow.
How do I pass navigation props from parent component to header?
Pass navigation.navigate to Child Component
https://reactnavigation.org/docs/use-navigation/
Thank you for reading, hopefully my explanation is clear enough.
I think your problem is somewhere here:
function AddCardScreen({ navigation }) {
return (
<View style={styles.addCardContainer}>
<AddCard navigation={navigation} />
</View>
);
}
There is no this, you're not in a class component, therefore this doesn't exists
The prop you are trying to pass should be called navigation and not navigate, since that's how you try to access it in the child component.
The navigation prop needs to be destructured inside the function argument function AddCardScreen({ navigation }), same as you already do for HomeScreen.