I am trying to call a function which is passed using props when onPress is clicked. Below is my custom component.
DrawerItem.js
import React from 'react';
import {
View,
Text,
StyleSheet,
Image,
TouchableOpacity
} from 'react-native';
import FastImage from 'react-native-fast-image';
const DrawerItem = (props) => (
<View style={styles.drawerItemContainer}>
<TouchableOpacity onPress={props.onPress}>
<FastImage source={props.icon} style={styles.icon} />
</TouchableOpacity>
<TouchableOpacity onPress={props.onPress}>
<Text style={styles.drawerItemText} >{props.title}</Text>
</TouchableOpacity>
</View>
);
export default DrawerItem;
Below is my custom component where I am using DrawerItem Component:
SideMenu.js:
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import {NavigationActions, SafeAreaView} from 'react-navigation';
import {ScrollView, Text, View, StyleSheet,ImageBackground, StatusBar, TouchableOpacity} from 'react-native';
import FastImage from 'react-native-fast-image';
import DrawerItem from './DrawerItem';
class SideMenu extends Component {
//This is the function which is not being called
navigateToScreen = (route) => () => {
console.log('inside navigate screen');
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
}
render () {
return (
<View style={styles.container}>
<ImageBackground source={require('../../resources/images/drawer_background.png')} style={{width: '100%', height: '100%'}}>
<View style={styles.drawer}>
<View style={styles.header}>
<FastImage style={styles.profilePicture} source={{uri: 'https://assets.entrepreneur.com/content/3x2/1300/20150406145944-dos-donts-taking-perfect-linkedin-profile-picture-selfie-mobile-camera-2.jpeg'}}/>
<View style={styles.headerDetails}>
<Text style={styles.displayName}>Jen William</Text>
<Text style={styles.email}>jen#williams.com</Text>
</View>
</View>
<View style={styles.drawerBody}>
//Below is how I am pasing navigateToScreen function
<DrawerItem onPress={() => this.navigateToScreen('Profile')} icon={require('../../resources/images/myprofile_icon.png')} title='My Profile'/>
<DrawerItem icon={require('../../resources/images/cardrequest_icon.png')} title='Card Requests'/>
<DrawerItem icon={require('../../resources/images/search_icon.png')} title='Search'/>
<DrawerItem icon={require('../../resources/images/add_icon.png')} title='My Cards'/>
<DrawerItem icon={require('../../resources/images/signout_icon.png')} title='Sign Out'/>
</View>
</View>
</ImageBackground>
</View>
);
}
}
SideMenu.propTypes = {
navigation: PropTypes.object
};
export default SideMenu;
Note: The props are being passed for sure as other values being passed
are accessible
Can someone please tell me what I am doing wrong?
It's probably a binding issue.
Instead of
onPress={() => this.navigateToScreen('Profile')}
Try:
onPress={this.navigateToScreen('Profile')}
Check your function :
navigateToScreen = (route) => () => {
console.log('inside navigate screen');
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
}
It should be like this :
navigateToScreen = (route) => {
console.log('inside navigate screen');
const navigateAction = NavigationActions.navigate({
routeName: route
});
this.props.navigation.dispatch(navigateAction);
}
There should not be extra brackets
Well! This may be funny. But believe me. I've experienced the same error and my code is simply as below,
<TouchableOpacity onPress = {() => console.log('Hi')}>
<Text> Click Me! </Text>
</TouchableOpacity>
After 15 minutes of time, I just existed from my console to restart my app. On pressing my npm console just thrown all of console logs.
Yah, sometimes npm console on my windows machine goes crazy to make me believe problem with my code.
Depending on how you are running your code, this might not work. use onClick
Try this instead
<TouchableOpacity onClick={...}>
...
</TouchableOpacity>
Related
I am trying to make a Todo List creater with 2 nested modals. Each one of the modals passes a state to the Todo Component which is then published in the App.js. The App.js has an initial hook state for showModal1 as false, but it changes to true when I press the button to open the Modal1.
The first modal (Modal1) is suposed to pass the task state to the second modal (Modal2).
import React,{useState} from 'react';
import {StyleSheet, Text, View, TouchableOpacity, TextInput, Modal} from 'react-native';
import {AntDesign} from '#expo/vector-icons';
import Modal2 from './Modal2';
function Modal1(props) {
const [showModal2, setShowModal2] = useState(false)
const [task, setTask] = useState('')
const toggleShowModal2 = (task) => {
setShowModal2(!showModal2);
}
function handleTask(value) {
setTask(value)
}
return(
<View behavior='padding'>
<Modal animationType='slide' visible={showModal2} onRequestClose={toggleShowModal2}>
<Modal2 closeModal={toggleShowModal2}/>
</Modal>
<TouchableOpacity onPress={props.closeModal}>
<AntDesign name='close' size={24} color='black'/>
</TouchableOpacity>
<View>
<Text>First Step</Text>
<Text>Task</Text>
<TextInput placeholder='What is the task?' value={task} onChangeText={handleTask}/>
</View>
<View>
<TouchableOpacity onPress={() => toggleShowModal2(task)}>
<AntDesign name='arrowright' size={40} color='black'/>
</TouchableOpacity>
</View>
</View>
);
};
And the second modal should be able to pass the time state and then create the Todo with the state values.
import React, {useState, useEffect} from 'react';
import { StyleSheet, Text, View, KeyboardAvoidingView, TouchableOpacity, TextInput, ScrollView} from 'react-native';
import {AntDesign} from '#expo/vector-icons';
function Modal2(props) {
const [time, setTime] = useState('')
function handleTime(value) {
setTime(value)
}
function createTodo(){
const list = {task, time};
setTask('')
setTime('')
props.addList(list);
props.closeModal();
}
return(
<View behavior='padding'>
<TouchableOpacity onPress={props.closeModal}>
<AntDesign name='close' size={24} color='black'/>
</TouchableOpacity>
<View>
<Text>Second Step</Text>
<Text>Time</Text>
<TextInput placeholder='When are you going to do it?' value={time} onChangeText={handleTime}/>
</View>
<View>
<TouchableOpacity onPress={createTodo}>
<AntDesign name='arrowright' size={40} color='black'/>
</TouchableOpacity>
</View>
</View>
);
};
However, whenever I try to publish the Todo, the following error pops up:
ReferenceError: Can't find variable: task
I am new to React (and React Hooks) and I don't know if it is possible to save state from one function to another in a similar way.
In order to access variables defined in another component, you need to pass them as props,
so you can pass the variables as props in Modal1
...
<Modal2 closeModal={toggleShowModal2} task={task} setTask={setTask} />
...
and access them in Modal2 like so,
function createTodo(){
const { task, setTask } = props;
const list = { task, time };
setTask('')
setTime('')
props.addList(list);
props.closeModal();
}
So the scenario is, I want to implement a GoBack Icon at the top of my app,that leads back to previous page. I am using stack navigator and disabled the header. So I need a go back button. I decided to make a component for that, here is my code,
import { Ionicons } from '#expo/vector-icons';
function GoBack(){
return (
<Ionicons onPress={()=>this.props.navigation.goBack()} name="md-arrow-back" size={24} color="#0c85f3" />
);
}
export default GoBack;
if I do it like this then an it shows me a typeError: Cannt read property 'goBack' of undefined.but if I put onPress as props and implement the same line of code onPress={()=>this.props.navigation.goBack()} it works perfectly.
I can not apply onPress props everywhere. Its a app with a lot of screens. How do I apply it in the component itself?
I think I am in lack of deep understanding of React navigation. Please help me understand the solution too.
Here is how I am using the GoBack Component:
import React, { Component } from 'react';
import {View, StyleSheet, Text, FlatList} from 'react-native';
import TestRoomtData from '../../../testData';
import HistoryCard from '../../../components/cards/historyUserCard';
import GoBack from '../../../shared/goBackButton';
class UserHistory extends Component{
render(){
return(
<View style={styles.container}>
<View style={{flexDirection:"row",}}>
<GoBack />
<Text style={styles.title}>History</Text>
</View>
<Text style={styles.title01}>Past Patients</Text>
<FlatList
data={TestRoomtData}
renderItem={({item})=>([
<View>
<HistoryCard
prescription={item.prescription}
diagnosis={item.diagnosis}
date={item.date}
source={{
uri: item.uri
}}
btnText01="More"
btnText02="Edit"
onPressBtn2={()=> this.props.navigation.navigate('Edit History') }/>
</View>
]
)}
/>
</View>
);
}
}
It's a functional component,
First : so you can't use this. ,
Second : you forgot to get props
function GoBack(props){ // <---- HERE
return (
<Ionicons
onPress={props.navigation.goBack} // <---- HERE
name="md-arrow-back" size={24} color="#0c85f3" />
);
}
In functional component in react, you can't use this keyword to access props.
In the current situation you have to pass navigation prop in GoBack
something like this,
function Goback(props) {
const { navigation } = props;
return (
<Ionicons
onPress={() => navigation.goBack()}
name="md-arrow-back"
size={24}
color="#0c85f3"
/>
);
}
Now, call the GoBack component,
<GoBack
navigation={{ goBack: () => goBack() }}
/>
So I am following Academind tutorial on youtube on react native but i can't seem to get to work the passing of values between tow components.
In startgamescreen on this line onPress={()=>props.onGame(selNumber)} I seem to follow him and pass selNumber but the error I get is onGame is not a function and undefined
and in App.js
const gameHandler=(selNum)=>{
setUserNumber(selNum);
};
let content=<StartGameScreen onGame={gameHandler} />;
Here I seem to exactly follow him and pass the gamehandler but I still don't get what went wrong. Please help me I have tried to debug this code for a while now.
StartGameScreen.js
import React, {useState} from 'react';
import { View, StyleSheet, Alert ,Text, Button, TouchableWithoutFeedback,Keyboard} from 'react-native';
import NumberComponents from '../components/NumberComponent';
import Card from '../components/Card';
import Colors from '../constants/colors';
import Input from '../components/Input';
const StartGameScreen = props => {
const [enteredValue,setEnteredValue]=useState('');
const [confirmed,setConfirmed]=useState(false);
const [selNumber,setSelNumber]=useState('');
const numberHandler =textinput=>{
setEnteredValue(textinput.replace(/[^0-9]/g,''));
};
let confirmedOutput;
if(confirmed){
confirmedOutput=<Card style={styles.confirm}>
<Text>You Selected:</Text>
<NumberComponents children={selNumber}/>
<Button title='Start Game' onPress={()=>props.onGame(selNumber)}/>
</Card>
}
const resetInputHandler=()=>{
setEnteredValue('');
setConfirmed(false);
};
const confirmButtonHandler=()=>{
const chosenNum=parseInt(enteredValue);
if(isNaN(chosenNum) || chosenNum<=0 || chosenNum>99){
Alert.alert(
'InValid Number',
'Please Enter Valid Number Between 1 and 99',
[{text:'Okay',style:'destructive',onPress:resetInputHandler}]
)
return;
}
setConfirmed(true);
setEnteredValue('');
setSelNumber(chosenNum);
Keyboard.dismiss();
};
return (
<TouchableWithoutFeedback onPress={()=>{Keyboard.dismiss();}}>
<View style={styles.screen}>
<Text style={styles.title}> Start A New Game </Text>
<Card style={styles.inputContainer}>
<Text style={{ color: 'green', fontSize: 15 }}>Choose A Number</Text>
<Input
keyboardType='number-pad'
maxLength={2}
style={styles.input}
blurOnSubmit
onChangeText={numberHandler}
value={enteredValue}
/>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button
title='Reset'
color={Colors.accent}
onPress={resetInputHandler} />
</View>
<View style={styles.button}>
<Button
title='Confirm'
onPress={confirmButtonHandler}
color='orange' />
</View>
</View>
</Card>
{confirmedOutput}
</View>
</TouchableWithoutFeedback>
);
};
in App.js
import React,{ useState } from 'react';
import { StyleSheet, View } from 'react-native';
import Header from './components/Header';
import StartGameScreen from './screens/StartGameScreen';
import GameScreen from './screens/StartGameScreen';
export default function App() {
const [userNumber,setUserNumber]=useState();
const gameHandler=(selNum)=>{
setUserNumber(selNum);
};
let content=<StartGameScreen onGame={gameHandler} />;
if(userNumber){
content=<GameScreen userChoice={userNumber}/>;
}
return (
<View style={styles.screen}>
<Header title="Guess A Number"/>
{content}
</View>
);
}
const styles = StyleSheet.create({
screen:{
flex:1,
}
});
You need to add onGame={gameHandler} into this component:
if (userNumber) {
content = <GameScreen onGame={gameHandler} userChoice={userNumber} />;
}
Since GameScreen and StartGameScreen are the same components,
import StartGameScreen from './screens/StartGameScreen';
import GameScreen from './screens/StartGameScreen';
in the second case when userNumber is not false the GameScreen component was called without the onGame props.
See the working stripped down version in codesandbox:
https://codesandbox.io/s/affectionate-wright-3bccd
Hello if there are not parent-child relation between your components,you can use Event like DeviceEventEmitter.
Here is a good link for example: [https://callstack.com/blog/sending-events-to-javascript-from-your-native-module-in-react-native/][1]
I'm a beginner in React Native and I'm trying to display my data from Google Firebase in a FlatList. There are no errors that pop up, but nothing is shown in my list. I know that the componentDidMount() section works, as when I add a console.log inside it shows that offers has the correct objects inside. I'm not sure why it doesn't show up on the screen though...
import React, {Component} from 'react';
import {View, Text, StyleSheet, TextInput, SafeAreaView, Platform, Image, FlatList, TouchableHighlight} from "react-native";
import { List, ListItem, Divider } from 'react-native-elements';
import Icon from "react-native-vector-icons/Ionicons";
import { db } from '../config';
let offersRef = db.ref('/offers');
class Home extends Component {
state = {
offers: [],
currentUser: null
};
componentDidMount() {
let mounted = true;
if(mounted){
offersRef.on('value', snapshot => {
let data = snapshot.val();
let offers = Object.values(data);
this.setState({ offers });
});
}
return () => mounted = false;
}
pressRow()
{
console.log(item)
}
renderItem(item){
return(
<TouchableHighlight onPress={() => {this.pressRow(item)}}>
<Text>
{item.name}
</Text>
</TouchableHighlight>
)
}
render() {
const { currentUser } = this.state
return (
<SafeAreaView style={{ flex: 1 }}>
<FlatList>
data = {this.state.offers}
renderItem = {({ data }) => (
<TouchableHighlight onPress={() => {this.pressRow(data)}}>
<Text>
{data.name}
</Text>
</TouchableHighlight>
) }
</FlatList>
</SafeAreaView>
);
}
}
export default Home;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
My code is above, it would be very much appreciated if someone is able to help! Thank you...
Hey please do the following changes in your render method:-
Replace "data" in renderItem with "item" and with in renderItem where ever accordingly.
<SafeAreaView style={{ flex: 1 }}>
<FlatList
data = {this.state.offers}
renderItem = {({item} ) => (
<TouchableHighlight onPress={() => {this.pressRow(item)}}>
<Text>
{item.name}
</Text>
</TouchableHighlight>
) }
/>
</SafeAreaView>
I'm the newbie of the react-native and study with the complete code. But I can't understand the diffrence between "const" before export and after render. for example:
const { height, width } = Dimensions.get("window");
export default class App extends React.Component {
state = {
newToDo: ""
};
render() {
const { newToDo } = this.state;
why I ask this is because my first init is not "export default class App extends React.Component {" but "export default function App() {". So I can't assign const or assign it and it cause the Error showing the message
TypeError:undefined is not an object (evaluating 'this.state')
this is my code :
import React from "react";
import {
StyleSheet,
Text,
View,
Dimensions,
TextInput,
Platform,
ScrollView
} from "react-native";
import ToDo from "./ToDo";
const { height, width } = Dimensions.get("window");
export default function App() {
const state = {
newToDo: ""
};
const { newToDO } = this.state;
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Good or Bad</Text>
<Text style={styles.subTitle}>Check Daily your habit</Text>
</View>
<View style={styles.content}>
<Text style={styles.contentTitle}>To Do List</Text>
<TextInput
style={styles.input}
placeholder={"New to do"}
value={newToDO}
onChangeText={this._controllNewToDo}
returnKeyType={"done"}
autoCorrect={false}
/>
<ScrollView>
<ToDo />
</ScrollView>
</View>
</View>
);
_controllNewToDo = text => {
this.setState({
newToDO: text
});
};
}
You can't use this.setState({}) inside a functional components. So you should use a normal class component to be able to call this.setState or use Hooks to update state inside functionals components.
import React, {Component} from "react";
import {
StyleSheet,
Text,
View,
Dimensions,
TextInput,
Platform,
ScrollView
} from "react-native";
import ToDo from "./ToDo";
const { height, width } = Dimensions.get("window");
class App extends Component {
state = {
newToDo: ""
};
_controllNewToDo = text => {
this.setState({
newToDO: text
});
};
render(){
const { newToDO } = this.state;
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Good or Bad</Text>
<Text style={styles.subTitle}>Check Daily your habit</Text>
</View>
<View style={styles.content}>
<Text style={styles.contentTitle}>To Do List</Text>
<TextInput
style={styles.input}
placeholder={"New to do"}
value={newToDO}
onChangeText={this._controllNewToDo}
returnKeyType={"done"}
autoCorrect={false}
/>
<ScrollView>
<ToDo />
</ScrollView>
</View>
</View>
);
}
}
export default App;
Try this code!
As i mentioned below, If you need to use state and setState({}) you should use inside class components. otherwise you should use Hooks, check this .I think this will help you to understand.
import React from 'react';
import {
StyleSheet,
Text,
View,
Dimensions,
TextInput,
Platform,
ScrollView,
} from 'react-native';
const { height, width } = Dimensions.get('window');
export default class App extends React.Component {
state = {
newToDo: 'wwe',
};
_controllNewToDo = text => {
this.setState({
newToDO: text,
});
};
render() {
const { newToDO } = this.state;
return (
<View>
<View>
<Text>Good or Bad</Text>
<Text>Check Daily your habit</Text>
</View>
<View>
<Text>To Do List</Text>
<TextInput
style={{ height: 60 }}
placeholder={'New to do'}
value={newToDO}
onChangeText={this._controllNewToDo}
returnKeyType={'done'}
autoCorrect={false}
/>
<ScrollView
style={{ justifyContent: 'center', alignItems: 'center' }}>
<Text>{newToDO}</Text>
</ScrollView>
</View>
</View>
);
}
}
Feel free for doubts
In functional component you have use useState hook to manage state.Try this,
import React, { useState } from "react";
import {
StyleSheet,
Text,
View,
Dimensions,
TextInput,
Platform,
ScrollView
} from "react-native";
import ToDo from "./ToDo";
const { height, width } = Dimensions.get("window");
export default function App() {
const [newToDo, setNewToDo] = useState("");
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Good or Bad</Text>
<Text style={styles.subTitle}>Check Daily your habit</Text>
</View>
<View style={styles.content}>
<Text style={styles.contentTitle}>To Do List</Text>
<TextInput
style={styles.input}
placeholder={"New to do"}
value={newToDo}
onChangeText={_controllNewToDo}
returnKeyType={"done"}
autoCorrect={false}
/>
<ScrollView>
<ToDo />
</ScrollView>
</View>
</View>
);
const _controllNewToDo = text => {
setNewToDo(text);
};
}