I'm pretty new to the idea of states in react native and have trouble using them to change the states of the components. I have three text components one which is a question and another two are answers (yes and no), and another text component that checks if my answer to the question is write, so the check text component. When I click on yes for a certain question the state of the last check component should change to 'right' if the answer was yes or to 'wrong' if the answer is no. So basically, this is what I want to do :
This is what I have so far:
This is the error I get :
This is the code I have so far:
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Alert, ScrollView, Image } from 'react-native';
// import TextComp from './components/Home2'
export default function App() {
const [answer, setAnswer] = useState('answer');
const [correctAns, setCorrectAns] = useState('');
const useEffect = () => {
if (answer == 'answer') {
setCorrectAns('please answer!');
} else if (answer == 'Yes') {
setCorrectAns('Right');
} else if (answer == 'No') {
setCorrectAns('Wrong');
};
};
const corAns = () => { Alert('Your answer was ', correctAns) }
return (
<ScrollView style={styles.container}>
<View style={{ alignItems: 'center' }}>
<Image source={require('./images/pic.jpeg')} style={styles.uriImg} />
<Text style={styles.title}>Is this Mt. Fuji?</Text>
<TouchableOpacity
onPress={() => setAnswer('Yes')}>
<Text style={styles.text}>Yes</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setAnswer('No')}>
<Text style={styles.text}>No</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={corAns}>
<Text style={styles.text2}>Check</Text>
</TouchableOpacity>
<Image source={require('./images/yellow.png')} style={styles.uriImg} />
<Text style={styles.title}>Is this red color?</Text>
<TouchableOpacity
onPress={() => setAnswer('Yes')}>
<Text style={styles.text}>Yes</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => setAnswer('No')}>
<Text style={styles.text}>No</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={corAns}>
<Text style={styles.text2}>Check</Text>
</TouchableOpacity>
</View>
</ScrollView>);
}
Can anyone tell me how it could be done? Thanks!
use useEffect like this
useEffect(() => {
if (answer === 'Yes') {
Alert.alert('Right')
}
if (answer === 'No') {
Alert.alert('Wrong')
}
}, [ answer ])
or by pressing check button
const checkAnswer = () => {
if (answer === 'Yes') {
Alert.alert('Right')
}
if (answer === 'No') {
Alert.alert('Wrong')
}
if (answer === 'answer') {
Alert.alert('please answer')
}
}
set check button onPress={checkAnswer}
Related
I'm having issue on how to change color of the status container while passing props from dummy data. I'm able to change font color of the status but not the container color same as the font color. Please do help me out. Below i have attached the picture of UI and the code. I used this method to change the color for the font of the status:
<Text style={[GlobalStyle.ReceiptAccept, migrateData.status === "Declined" && GlobalStyle.ReceiptDeclined, migrateData.status === "Pending" && GlobalStyle.ReceiptPending]}>{migrateData.status}</Text>
UI Picture:
PendingReceipt.js
import React, {useState} from 'react';
import {View, Text, TouchableOpacity, Image, FlatList,ScrollView} from 'react-native';
import GlobalStyle from '../components/GlobalStyle';
import { HeaderBar2 } from '../components/HeaderBar';
import {GrayCustomView} from './../components/styles';
const ReceiptDetailsScreen = ({route, navigation}) => {
const {migrateData} = route.params;
return (
<ScrollView style={[GlobalStyle.GrayScrollView]}>
<HeaderBar2/>
<View style={[GlobalStyle.AlignReceiptDetailContainer]}>
<View style={[GlobalStyle.ReceiptDetailContainer]}>
<View style={[GlobalStyle.AlignReceiptHeaderContainer]}>
<View style={[GlobalStyle.ReceiptHeader1]}>
<Text style={[GlobalStyle.ReceiptListTitle]}>{migrateData.receiptnum}</Text>
</View>
<View style={[GlobalStyle.ReceiptPendingContainer]}>
<Text style={[GlobalStyle.ReceiptAccept, migrateData.status === "Declined" && GlobalStyle.ReceiptDeclined, migrateData.status === "Pending" && GlobalStyle.ReceiptPending]}>{migrateData.status}</Text>
</View>
</View>
</ScrollView>
)
}
dummy.js:
Add {"backgroundColor":"black"} in the view and change the color as you want
<View style={[GlobalStyle.ReceiptPendingContainer,{"backgroundColor":status === "Pending" ? "yellow": status === "Declined" ? "red" : "green" }]}>
<Text style={[GlobalStyle.ReceiptAccept, migrateData.status === "Declined" && GlobalStyle.ReceiptDeclined, migrateData.status === "Pending" && GlobalStyle.ReceiptPending]}>{migrateData.status}</Text>
</View>
You can try this:
const getTextStyle = (status) => {
switch(status){
case "Declined":
return GlobalStyle.ReceiptDeclined
case "Pending":
return GlobalStyle.ReceiptPending
default:
return {}
}
}
return (
...
<Text style={[GlobalStyle.ReceiptAccept, getTextStyle()]}>{migrateData.status}</Text>
...
)
I am new to react native and simply can not find the reason for the infinity loop error I spent my last few hours with... Here is what is happening:
I have the following custom component
import { TouchableOpacity, StyleSheet, View, Text } from "react-native";
import { FontAwesome } from "#expo/vector-icons";
function AnswerContainer_CheckBox(props) {
const [checked, setChecked] = useState(false);
const checkedHandler =()=>{
if (checked == false) {
setChecked(true);
} else {
setChecked(false);
}
}
return (
<View>
<TouchableOpacity
onPress={() => {
checkedHandler();
props.true_1;
}
}
>
<View style={styles.mainContainer}>
<View style={styles.icon}>
<FontAwesome
name={checked == true ? "check-square" : "square-o"}
size={24}
color={checked == true ? "#3787FF" : "#BFD3E5"}
/>
</View>
<Text style={styles.checkButtonText}>{props.title}</Text>
</View>
</TouchableOpacity>
</View>
);
}
I use that Component in my screen like this:
function myScreen(props) {
const [true1, setTrue1] = useState(false);
const setTrue_1_Handler = () => {
switch (true1) {
case false:
setTrue1(true);
alert("true");
break;
case true:
setTrue1(false);
break;
}
};
return (
<SafeAreaView>
<AnswerContainer_CheckBox true_1={setTrue_1_Handler()} title="Test_1" />
<AnswerContainer_CheckBox title="Test_2" />
<AnswerContainer_CheckBox title="Test_3" />
</SafeAreaView>
);
}
Whenever I navigate to "myScreen", the infite loop error apperas and crashes the app - even though I didn't press that button yet.
Any ideas? I know the issue has come up a few times but I still didn't make it work (useEffect didn't help somehow...).
Thanks
I dont understand how to hide and show Components dependet und a state. I came up with the following code, but i think its wrong, because the UI isnt being update after i press the "login" button. Is there a general way to do this? I also aks myself how to handle changing between "Dialogs". For example i want that when a Button is clicked, that the current Dialog is closed and the target Dialog is renderd. How could i do this?
import React from 'react';
import { ImageBackground, StyleSheet, TouchableOpacity, Text, View, TextInput} from 'react-native';
function WelcomeScreen(props) {
var loginDialog = {
visible: false
};
var signUpDialog = {
visible: false
};
var welcomeDialog = {
visible: true
};
const login = loginDialog.visible ? (
<View style={styles.loginDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const signup = signUpDialog.visible ? (
<View style={styles.signUpDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const welcome = welcomeDialog.visible ? (
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={changeState("login")}style={[styles.button, styles.login]}>
<Text style={styles.text}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={changeState("signup")} style={[styles.button, styles.signUp]}>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
</View>
) : null;
function changeState(mode){
if(mode === "login"){
console.log("Yes");
welcomeDialog.visible = false;
loginDialog.visible = true;
}else if(mode === "signup"){
welcomeDialog.visible = false;
signUpDialog.visible = true;
}
}
return (
<ImageBackground style={styles.background}
source={require('../assets/welcome_background.jpg')}>
{login}
{signup}
{welcome}
</ImageBackground>
);
}
export default WelcomeScreen;
Seems like you are new to react you should read about state https://reactjs.org/docs/state-and-lifecycle.html.
You should use useState in functional component or setState in class component also I really recomend to use third party library for dialogs/modals.
https://github.com/mmazzarolo/react-native-dialog
https://github.com/react-native-modal/react-native-modal
import React, {useState} from 'react';
import { ImageBackground, StyleSheet, TouchableOpacity, Text, View, TextInput} from 'react-native';
function WelcomeScreen(props) {
const [loginDialog,setLoginDialog] = useState(false);
const [signUpDialog ,setSignUpDialog ] = useState(false);
const [welcomeDialog ,setWelcomeDialog ] = useState(false);
const login = loginDialog ? (
<View style={styles.loginDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const signup = signUpDialog? (
<View style={styles.signUpDialog}>
<TextInput style={styles.input}/>
</View>
) : null;
const welcome = welcomeDialog? (
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={changeState("login")}style={[styles.button, styles.login]}>
<Text style={styles.text}>Log In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={changeState("signup")} style={[styles.button, styles.signUp]}>
<Text style={styles.text}>Sign Up</Text>
</TouchableOpacity>
</View>
) : null;
const changeState = (mode) => {
if(mode === "login"){
console.log("Yes");
setWelcomeDialog(false);
setLoginDialog(true);
}else if(mode === "signup"){
setWelcomeDialog(false);
setSignUpDialog(true);
}
}
return (
<ImageBackground style={styles.background}
source={require('../assets/welcome_background.jpg')}>
{login}
{signup}
{welcome}
</ImageBackground>
);
}
export default WelcomeScreen;
When I run this inside a function, and click either one of the touchableOpacity I have to save the code for it to check the id number then return the correct outcome
const pressHandler = (id) => {
if (id == 1) {
Pressedinfo = <View>
<Text>one</Text>
</View>
} else if (id = 2) {
Pressedinfo = <View>
<Text>two</Text>
</View>
}
}
in the return (view):
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
{Pressedinfo}
You need to use state. Move your react element out of the function and just manipulate the string in state.
In your constructor create a state:
constructor(props){
super(props);
this.state = {textString: ''}
}
const pressHandler = (id) => {
if (id === 1) {
this.setState({textString : 'one'})
}
else if(id === 2) {
this.setState({textString : 'two'})
}
}
For the template:
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
<View>
<Text>{this.state.textString}</Text>
</View>
This is how I would try.
import React, { Component, useState } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
const App = () => {
const [Pressedinfo, setPressedInfo] = useState(null)
const pressHandler = (id) => {
if (id == 1) {
setPressedInfo(<View><Text>one</Text></View>)
} else if (id = 2) {
setPressedInfo(<View><Text>two</Text></View>)
}
}
return (
<View>
<TouchableOpacity onPress={() => pressHandler(1)}>
<Text style={Styles.Text1}>1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => pressHandler(2)}>
<Text style={Styles.Text1}>2</Text>
</TouchableOpacity>
{Pressedinfo}
</View>
)
}
use this.state method to change the components without re rendering the page.
I'm pretty new to Native React. I just went through the Expo tutorial and I am trying to make a Button that can consolidate the TouchableOpacity and Text into one component for re-usability.
I keep getting "Invariant Violation: Button(): Nothing was returned from render." I also referenced here.
Stylesheet is not in code below, not a concern.
Thanks!
import React from 'react';
import { Image, Platform, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import * as Sharing from 'expo-sharing';
function Button(props)
{
return
(
<TouchableOpacity
onPress={props.command} style = {styles.button}>
<Text style={styles.buttonText}>{props.t}</Text>
</TouchableOpacity>
);
}
export default function App() {
const [selectedImage, setSelectedImage] = React.useState(null);
let openImagePickerAsync = async() => {
let permissionResult = await ImagePicker.requestCameraRollPermissionsAsync();
if (permissionResult.granted === false)
{
alert("Permission to access camera roll is required!");
return;
}
let pickerResult = await ImagePicker.launchImageLibraryAsync();
if (pickerResult.cancelled === true)
{
return;
}
setSelectedImage({localUri:pickerResult.uri});
};
let openShareDialogAsync = async() => {
if (!(await Sharing.isAvailableAsync()))
{
alert(`The image is available for sharing at: ${selectedImage.remoteUri}`);
return;
}
Sharing.shareAsync(selectedImage.localUri);
};
if (selectedImage !== null)
{
return(
<View style={styles.container}>
<Image
source ={{uri:selectedImage.localUri}}
style={styles.thumbnail}
/>
<TouchableOpacity onPress={openShareDialogAsync} style={styles.button}>
<Text style={styles.buttonText}>Share this photo</Text>
</TouchableOpacity>
</View>
);
}
return (
<View style={styles.container}>
<Image source={{uri: "https://i.imgur.com/TkIrScD.png"}} style={styles.logo} />
<Text style = {styles.instructions}>
To share a photo from your phone with a friends, just press the button below!
</Text>
<Button command = {openImagePickerAsync} t = "Pick a photo"/>
{/*
<TouchableOpacity
onPress={openImagePickerAsync} style = {styles.button}>
<Text style={styles.buttonText}>Pick a photo</Text>
</TouchableOpacity>
*/}
</View>
);
}
Nothing wrong with your code only thing is your return statement. When you place the opening bracket in the next line it will not return anything and your actual component code will be unreachable as it will be considered as a separate block. Just change it to the code below.
function Button(props) {
return (
<TouchableOpacity onPress={props.command} style={styles.button}>
<Text style={styles.buttonText}>{props.t}</Text>
</TouchableOpacity>
);
}