How can I change an object without refreshing the file? - javascript

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.

Related

Getting data from a class component to Functional component - React Native

I'm pretty new to React Native and don't have the most experience with javascript so although this may be very simple I have no idea what to do. I have a class Component which acts like a popup in my app. It pops up on press of a touchable opacity and displays a little menu. I am trying to get the id of the button that is pressed on that menu and send it back to the functional component main screen (where the touchable opacity to open the menu is). I can get the id of the button but I'm struggling to get this data out of the popup and back into my main screen(functional component)
Here is my Code for the Main Screen:
import { StyleSheet, Text, View, Image,TouchableOpacity} from 'react-native'
import React,{useState} from 'react'
import tw, { create } from 'twrnc';
import Map from "../components/Map"
import { SafeAreaView } from 'react-native-safe-area-context';
import { BottomPopup } from '../components/popup';
import { selectTrucks} from '../slices/navSlice';
import { useSelector } from 'react-redux';
const Logistics = () => {
const Trucks = useSelector(selectTrucks);
let popupRef = React.createRef()
const onShowPopup = () => {
popupRef.show()
}
const onClosePopup = () => {
popupRef.close()
}
return (
<View style={{flex:1,resizeMode:'contain'}}>
<View style={tw`h-12/16`}>
<Map/>
</View>
<TouchableOpacity onPress={onShowPopup} style={{top:'-68%'}}>
<Image
source = {{uri: "https://icon-library.com/images/app-menu-icon/app-menu-icon-21.jpg" }}
style = {{width:'20%', height:40,resizeMode:'contain'}}
/>
<Text style={{color:'black',paddingLeft:2,fontSize: 26,fontWeight:"bold",top:-37,left:70}}>Truck {}</Text>
</TouchableOpacity>
<BottomPopup
title = "Select Option"
ref = {(target)=> popupRef = target}
onTouchOutside={onClosePopup}
data={Trucks.TrucksInfo}
/>
<SafeAreaView style={{top:'-13%'}}>
<Text style={{color:'darkgreen',paddingLeft:2,fontSize: 36,fontWeight:"bold"}}>123 Elmo Street</Text>
<Text style={{color:'darkgreen',paddingLeft:2,fontSize: 24,fontWeight:"bold"}}>L4L 6L8, Mississauga, Ontario</Text>
<Text style={{color:'darkgreen',paddingLeft:2,fontSize: 18,fontWeight:"bold"}}>Phone Number: 416-749-6857{'\n'}Client: Bobby Jeff{'\n'}Order Number: 7187181{'\n'}Packing Slip Number: 882929</Text>
<Text style={{color:'black',fontSize: 18,paddingLeft:2}}>Customer Notified: Yes at 2:32 PM</Text>
</SafeAreaView>
</View>
)
}
export default Logistics
const styles = StyleSheet.create({})
And Here is the code for the class component popup:
import { Modal,Dimensions,TouchableWithoutFeedback,StyleSheet,View,Text,FlatList,TouchableOpacity} from "react-native";
import React from "react";
import { useNavigation } from '#react-navigation/native';
import Logistics from "../screens/Logistics";
const deviceHeight = Dimensions.get('window').height
export class BottomPopup extends React.Component {
constructor(props){
super(props)
this.state = {
show:false
}
}
show = () => {
this.setState({show:true})
}
close = () => {
this.setState({show:false})
}
renderOutsideTouchable(onTouch) {
const view = <View style = {{flex:1,width:'100%'}}/>
if (!onTouch) return view
return (
<TouchableWithoutFeedback onPress={onTouch} style={{flex:1,width:'100%'}}>
{view}
</TouchableWithoutFeedback>
)
}
renderTitle = () => {
const {title} = this.props
return (
<View style={{alignItems:'center'}}>
<Text style={{
color:'#182E44',
fontSize:25,
fontWeight:'500',
marginTop:15,
marginBottom:30,
}}>
{title}
</Text>
</View>
)
}
renderContent = () => {
const {data} = this.props
return (
<View>
<FlatList
style = {{marginBottom:130}}
showsVerticalScrollIndicator = {false}
data={data}
renderItem={this.renderItem}
extraData={data}
keyExtractor={(item,index)=>index.toString()}
ItemSeparatorComponent={this.renderSeparator}
contentContainerStyle={{
paddingBottom:40
}}
/>
</View>
)
}
renderItem = ({item}) => {
return(
<TouchableOpacity
onPress={() => {this.close(),console.log(item.id)}}
>
<View style = {{height:50,flex:1,alignItems:'flex-start',justifyContent:'center',marginLeft:20}}>
<Text style={{fontSize:18,fontWeight:'normal',color:"#182E44"}}>{item.name}</Text>
</View>
</TouchableOpacity>
)
}
renderSeparator = () => {
return(
<View
style={{
opacity:0.1,
backgroundColor:'#182E44',
height:1
}}
/>
)
}
render() {
let {show} = this.state
const {onTouchOutside,title} = this.props
return (
<Modal
animationType={"fade"}
transparent={true}
visible={show}
onRequestClose={this.close}
>
<View style={{flex:1, backgroundColor:"#000000AA",justifyContent:'flex-end'}}>
{this.renderOutsideTouchable(onTouchOutside)}
<View style={{
backgroundColor:'#FFFFFF',
width:'100%',
paddingHorizontal:10,
maxHeight:deviceHeight*0.4}}
>
{this.renderTitle()}
{this.renderContent()}
</View>
</View>
</Modal>
)
}
}
The console log in the render item function gets me the number i need i just need to get this number out and back into my logistics screen
What you can do is like onTouchOutside you can pass getId function as props which will return id.
I don`t have much experience with class component. So I have add sample code in functional component. You can refer this
const MainComponent = ()=>{
const getIdFunc = (id)=>{
//You will get id here
}
return(<View>
{/* pass function here */}
<PopUpComponent getIdFunc={getIdFunc}/>
</View>)
}
const PopUpComponent = (props)=>{
return(<TouchableOpacity
onPress={()=>{
//call function by passing id here
props.getIdFunc(id)
}}
>
</TouchableOpacity>)
}

React Native/TypeScript - How to manage state in functional component and apply flexible style with FlatList

Can anyone tell me how to solve these things?
1.if the list is pressed, I'd like to change the background color of the list
beige(#FFF5E7) to white(#FBFBFB)
2.Also, I'd like to change the read value of the Object fales to true with useState
Problem is that if I pressed the list, whole background color of the list will be changed.
index.tsx
import React, { useState } from 'react';
import { Text, View, TouchableOpacity, FlatList } from 'react-native';
import { useNavigation } from '#react-navigation/native';
import { DETAIL } from '../../sample';
import { Object } from './sample';
export default function sample() {
const [state, setState] = useState(Object);
const navigation = useNavigation();
let Element;
const renderItem = ({ item }) => {
const readState = () => {
navigation.navigate(NOTICE_DETAIL);
const readValue = [...state];
let value = { ...readValue[0] };
value.read = true;
readValue[0] = value;
setState(readValue);
};
if (state[0].read) {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FBFBFB' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
} else {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
}
return Element;
};
}
return (
<View style={{ flex: 1 }}>
<FlatList
extraData={Object}
data={Object}
renderItem={renderItem}
/>
</View>
);
}
Object.ts
export const Object = [
{
id: 1,
text: 'testtesttest',
content: 'testtesttest'
read: false
},
{
id: 2,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
id: 3,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
]
We can add inline styles into the component style props along with static styles,
For Example:
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: item.read ? '#FBFBFB' : 'FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
Problem in your readState function and if (state[0].read) {. You always change item with index 0 and then check state[0].read for all elements of your array.

Hide and Show Components in React Native

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;

Trouble getting states to work in react native

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}

React native - add currency prefix to TextInput

How can add a currency prefix to a TextInput in React Native? Here is an example of what I'm trying to achieve:
To give a bit more details - the TextInput should have a default value, for instance £10. I would like the currency sign to always be there.
At some point this value will be sent to a database so it should be converted to an integer.
My code so far (_renderSecondTile section):
import React, {Component} from 'react'
import {
Text,
View,
ListView,
ScrollView,
StyleSheet,
Image,
TouchableHighlight,
TextInput,
} from 'react-native'
class AppView extends Component {
state = {
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
isThirdTileActive: false,
textInputValue: '£10',
}
activateButton = buttonToActivate => {
const newState = Object.assign(
{},
{
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
},
{[buttonToActivate]: true},
)
this.setState(newState);
}
showThirdTile = tileToShow => {
this.setState({isThirdTileActive: tileToShow});
}
_renderSecondTile = () => {
if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
return(
<TouchableHighlight>
<View style={[styles.step, styles.stepTwo]}>
<View style={{flex: 1}}>
<Text style={styles.heading}>Enter amount</Text>
<View style={styles.amountInputContainer}>
<TextInput
onKeyPress={() => {this.showThirdTile(true)}}
style={styles.amountInput}
maxLength = {3}
value={this.state.textInputValue}
/>
</View>
</View>
</View>
</TouchableHighlight>
)
}
else{
return null;
}
}
_renderThirdTile = () => {
if(this.state.isSecondTitleActive){
return(
<View style={[styles.step, styles.stepThree]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Third tile</Text>
</View>
</View>
)
}
else{
return null;
}
}
render(){
const {isPlayerOneButtonActive} = this.state
return (
<ScrollView style={styles.container}>
<View style={[styles.step, styles.stepOne]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Pick player</Text>
<View style={styles.pickContainer}>
<TouchableHighlight onPress={() => {this.activateButton('isPlayerOneButtonActive')}}>
<Text>Player One</Text>
</TouchableHighlight>
<TouchableHighlight onPress={() => {this.activateButton('isPlayerTwoButtonActive')}}>
<Text>Player One</Text>
</TouchableHighlight>
</View>
</View>
</View>
{this._renderSecondTile()}
{this._renderThirdTile()}
</ScrollView>
)
}
}
Try using this:
class AppView extends Component {
state = {
isPlayerOneButtonActive: false,
isPlayerTwoButtonActive: false,
isThirdTileActive: false,
inputValue: 10,
}
inputChange = (e) => {
this.setState({inputValue: parseInt(e.target.value)});
if(!this.state.isThirdTileActive){
this.showThirdTile(true);
}
}
_renderSecondTile = () => {
if(this.state.isPlayerOneButtonActive || this.state.isPlayerTwoButtonActive) {
return(
<TouchableHighlight>
<View style={[styles.step, styles.stepTwo]}>
<View style={{flex: 1}}>
<Text style={styles.heading}>Enter amount</Text>
<View style={styles.amountInputContainer}>
<TextInput
style={styles.amountInput}
maxLength = {3}
onChange={this.inputChange}
value={"£" + this.state.inputValue}
/>
</View>
</View>
</View>
</TouchableHighlight>
)
}
else{
return null;
}
}
}
Note: I left out anything that I didn't change so my answer would be easier to read.
Here, I changed the textInputValue to inputValue. Now that value is stored as an integer so it is ready to be sent to the database. Whenever that value is changed in the text input field, the state will be updated by inputChange. inputChange will also call showThirdTile if the third tile isn't already active. Finally, the value of the text input will be inputValue concatenated with "£". In my last answer, I added , in the string version of the integer at every thousandth place. Since you have a max length of 3 in the text input field, that isn't necessary any more. If you ever need to increase the max length, I'd use this to convert:
var cashify = function(amountIn){
var amount = parseFloat(amountIn).toFixed(2);
var splitAmount = amount.split(".")[0];
var i = splitAmount.length-4;
while(i>=0){
splitAmount = splitAmount.slice(0,i+1) + "," + splitAmount.slice(i+1);
i=i-3;
}
return "\u00A3" + splitAmount + "." + amount.split(".")[1];
}
I hope that helps!

Categories

Resources