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]
Related
Description
Hello, I'm pretty new to React Native and I was trying to render a FlatList inside a ScrollView and I got an error mentioning this application of FlatList inside ScrollView is not proper and it may cause some scroll disorientations. So, I searched for solutions to this problem and found out there's ListHeaderComponent property for FlatList to render everything else inside ScrollView. I accomplished implementing this solution to my screen but now It doesn't respect to boundaries of SafeAreaView which is pretty annoying, I don't want to add hard-coded margin/padding to the outer ScrollView/View component. It wouldn't be pretty.
Current Implementation
screens/Home.js:
import React from 'react';
import {
View,
ScrollView,
StyleSheet,
Dimensions,
SafeAreaView
} from 'react-native';
import SearchBar from '../components/UI/SearchBar';
import CarouselSlider from '../components/UI/CarouselSlider';
import FeaturedProducts from '../components/UI/FeaturedProducts';
import RecommendedCategories from '../components/UI/RecommendedCategories';
import ProductList from '../components/UI/ProductList';
import { HeadingSecondary } from '../components/UI/Typography';
import CarouselSliderData from '../data/slider';
import MostSold from '../data/mostSold';
import Categories from '../data/categories';
const { width } = Dimensions.get('window');
const Home = props => {
const HeaderPart = (
<ScrollView>
<View style={styles.sectionSlider}>
<CarouselSlider
data={CarouselSliderData}
height={width*0.6}
width={width}
itemWidth={width - (width/5)}
/>
</View>
<View style={styles.sectionFeatured}>
<HeadingSecondary>Featured Products</HeadingSecondary>
<FeaturedProducts data={MostSold} />
</View>
<View style={styles.sectionRecommendedCategories}>
<HeadingSecondary>Recommended Categories For You</HeadingSecondary>
<RecommendedCategories data={Categories} />
</View>
<HeadingSecondary>Recommended Products For You</HeadingSecondary>
</ScrollView>
);
return (
<SafeAreaView style={styles.container}>
<SearchBar />
<View style={styles.sectionProducts}>
<ProductList
data={MostSold}
numColumns={2}
key={'Products'}
ListHeaderComponent={HeaderPart}
/>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center'
},
sectionSlider: {
height: width*0.6,
marginBottom: 12
}
});
export default Home;
components/UI/ProductList.js:
import React from 'react';
import {
View,
FlatList,
StyleSheet,
SafeAreaView
} from 'react-native';
import ProductItem from './ProductItem';
const ProductList = props => {
return (
<View style={styles.container}>
<FlatList
data={props.data}
renderItem={itemData =>
<ProductItem {...itemData.item} />
}
{...props}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1
}
});
export default ProductList;
Current Result Of Implementation
What I Want to Accomplish
Thanks in advance!
It seems like wrapping the FlatList with ListHeaderComponent/ListFooterComponent properties inside a View component is not correct. I have updated my code to below and it's solved.
screens/Home.js
...
const Home = props => {
...
return (
<SafeAreaView style={styles.container}>
<SearchBar />
<ProductList
data={MostSold}
numColumns={2}
key={'Products'}
ListHeaderComponent={HeaderPart}
/>
</SafeAreaView>
);
};
...
I'm working on a React Native project as a beginner. I'm creating a custom button called "RoundedButton" using touchableOpacity. But after creating this button when I use this and try to trigger an event using onPress like <RoundedButton onPress = {some function}/> it does not work.
Here is my code:
my RoundedButton.js code:
import React from 'react';
import {TouchableOpacity, Text, StyleSheet} from 'react-native';
import {colors} from '../utils/colors';
export const RoundedButton = ({
style = {},
textStyle = {},
size = 125,
...props
}) => {
return (
<TouchableOpacity style ={[styles(size).radius, style]}>
<Text style = {[styles(size).text, textStyle]}>{props.title}</Text>
</TouchableOpacity>
)
};
my Timer.js code where I uses the above custom button:
import React, {useState} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {colors} from '../../utils/colors';
import {fontSizes, spacing} from '../../utils/sizes'
import {Countdown} from '../../components/Countdown';
import {RoundedButton} from '../../components/RoundedButton';
export const Timer = ({focusSubject}) => {
const [isStarted, setIsStarted] = useState("false");
const onPress = () => setIsStarted("true");
return (
<View style={styles.container}>
<View style={styles.countdown}>
<Countdown isPaused={!isStarted}/>
</View>
<View>
<Text style={styles.title}>Focusing on: </Text>
<Text style={styles.task}>{focusSubject}</Text>
</View>
<RoundedButton title="Start" size={50} onPress={onPress}/>
<Text style={{color: 'white'}}>{isStarted ? "True" : "False"}</Text>
</View>
)
};
I have not included styles code to make it simpler to find the issue. I want to know the correct method to use onPress functionality in React Native. Please help as soon as possible. No error is shown, App is working but the pressing event is not working, so I am not able to find out the actual issue.
This is because you haven't passed onPress to TouchableOpacity. Just pass the prop and it should work just fine.
<TouchableOpacity style ={[styles(size).radius, style]} onPress={props.onPress}>
<Text style = {[styles(size).text, textStyle]}>{props.title}</Text>
</TouchableOpacity>
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();
}
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);
};
}
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>