How to send and display the value of a text input on another screen with native react? - javascript

I want to send the data of a text input that is stored in a variable to another screen and show the data that was saved in said variable
Try to pass the state of the variable by react-navigation but the problem is that I have 3 screens and I want to pass the data stored in the variable text from screen 1 to screen 3
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
text: '',
percentage: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.text
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('2', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Siguiente</Text>
</TouchableOpacity>
</View>
),
}
};
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
Alert.alert('Advertencia', 'Ingrese el porcentaje de su descuento');
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.Box}>
<ImageBackground source={require('../Icons/Regalo.png')} style={styles.Image}>
<View style={styles.ContainerInput}>
<TextInput
style={{ textAlign: 'center', color: '#fff', fontSize: 40, }}
type="numeric"
placeholder="%"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 0 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
<Text style={{ fontSize: 40, color: '#fff', textAlign: 'center' }}>
{this.state.text.split(' ').map((word) => word && '%').join(' ')}
</Text>
</View>
</ImageBackground>
</View>
</View>
);
}
}
export default Screen1;
My Screen Two:
class Screen2 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: ''
};
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state
var data = {
textData: params.textData
}
return {
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('1')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('3', { data })}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
}
};
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<View style={styles.InputContainer}>
<TextInput
multiline
style={styles.Input}
type="numeric"
placeholder="Describa los términos y condificones de tu regalos"
placeholderTextColor="rgb(196,196,196)"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 1 ? false : true
//set value in the state
this.setState({ text: text })
// set value to params
this.props.navigation.setParams({ isDisable: isDisable });
}} />
</View>
</View>
);
}
}
export default Screen2;
My Screen Three:
class Screen3 extends Component {
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data.textData,
text: '',
percentage: '',
};
}
static navigationOptions = ({ navigation }) => ({
headerLeft: (
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
<AntDesign
name="left"
color="rgba(0,0,0,0.5)"
size={30}
style={{ marginLeft: 5 }}
onPress={() => navigation.navigate('2')}
/>
<Text style={{ marginLeft: 20, color: '#000', fontSize: 17, fontWeight: 'bold' }}>Crear regalo</Text>
</View>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('4')}
style={styles.Btn}>
<Text style={styles.TxtBtn}>Crear</Text>
</TouchableOpacity>
</View>
),
});
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
let datos = [{
value: 'Banana',
}, {
value: 'Mango',
}, {
value: 'Pear',
}];
var data = {
textData: this.state.textData
}
return (
<View style={styles.container}>
<View style={styles.BoxandInput}>
<View style={styles.ContainerInput}>
<TextInput
style={styles.Input}
multiline
placeholder='Escriba una Descripcion'
placeholderTextColor="rgb(196,196,196)"
maxLength={203}
/>
</View>
<View style={styles.Box}>
<ImageBackground
source={require('../Icons/Regalo.png')}
style={styles.Image}>
<View style={styles.ContainerText}>
<Text style={styles.TextBox}>{data}</Text>
</View>
</ImageBackground>
</View>
</View>
<View style={styles.Regalos}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>--------------------------</Text>
<Text style={styles.RegalosText}>Cantidad de Regalos</Text>
<Text style={styles.line}>--------------------------</Text>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center', marginTop: 30 }}>
<TextInput
style={styles.RegalosInput}
placeholder='0'
placeholderTextColor='#000'
maxLength={6}
type='numeric'
/>
<View style={styles.LineInput} />
<Text style={{ fontSize: 10, color: '#ccc', textAlign: 'center', marginTop: 5 }}>60 regalos Disponibles</Text>
<TouchableOpacity style={{ marginTop: 15 }}>
<Text style={{ fontSize: 10, color: 'cyan', textAlign: 'center' }}>Comprar Regalos</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.ContainerServices}>
<View style={{ justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<Text style={styles.line}>-----------------------------------</Text>
<Text style={styles.RegalosText}>Servicios</Text>
<Text style={styles.line}>-----------------------------------</Text>
</View>
<Dropdown
dropdownMargins={{ min: 5, max: 10 }}
label='Favorite Fruit'
data={datos}
/>
</View>
</View>
);
}
}
export default
This Problem

You can create a data object and you can send it with navigation to next UI. You can pass the data object from UI 1 to UI 2 and then you can send it UI 3 from UI 2.
In the first UI you can create data variable like,
var data = {
textData: text
}
Include the above code inside navigationOptions of your code.
Then in the navigation call include the data object as well.
onPress={() => navigation.navigate('2', {data})}
In the second UI assign the passed value to a variable inside the constructor.
constructor(props) {
super(props);
this.state = {
textData: this.props.navigation.state.params.data. textData,
}
}
Then when you are going to navigate to the third UI create a data variable and send it as previously done.
var data = {
textData: this.state.textData
}
Pass this variable with navigate.navigation and access it from third UI similar as in the second UI.

Related

How to filter data of a List using Checkboxes in Expo?

I am trying to implement a function in Expo to filter my data using checkboxes. I have already completed my checkboxes and designed them accordingly. The data to be filtered is pulled from the Firebase database and displayed in the form of a list on my page. I have also created a button for the filtering, which is used so that when a user clicks this button, the filtering takes place according to the selection of the respective boxes. Attached is a picture that shows what has already been implemented and below the code for it. I would be very grateful if someone could help me with this, as I am relatively new to React Native and have not found anything in this regard.
Thanks in advance
Anbieterliste-Screen
function MyCheckbox() {
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
// THIS IS SIGN OUT BUTTON , WHEN USER CLICK FOR SIGNOUT THEN IT ASKS WHETHER HE/SHE IS SURE TO DO SO
const signOutFunc = async () => {
Alert.alert(
"Ausloggen?",
"Sind Sie sicher, dass Sie sich ausloggen möchten?",
[
{
text: "Bestätigen", onPress: async () => {
await AsyncStorage.removeItem('userName')
await AsyncStorage.removeItem('order')
firebase.auth().signOut();
navigation.navigate('Homepage');
}
},
{
text: "Abbrechen",
style: "cancel"
}
]
);
}
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Backware</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Bioprodukte</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Feinkost</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Griechische Spezialitäten</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Molkerei</Text>
</View>
<View style={styles.checkboxContainer}>
<MyCheckbox />
<Text style={styles.checkboxLabel}>Türkische Spezialitäten</Text>
</View>
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{restaurentList && restaurentList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}
A better approach to avoid duplication of code is to create a filterList array and create dynamic filters component.
I modified your code, check the comments for the explanation.
function MyCheckbox({addFilter, removeFilter, filterIndex}) { // ADD THIS PROPS TO ADD AND REMOVE FILTERS
const [checked, onChange] = useState(false);
function onCheckmarkPress() {
onChange(!checked);
checked ? addFilter(filterIndex) : removeFilter(filterIndex)
}
return (
<Pressable
style={[styles.checkboxBase, checked && styles.checkboxChecked]}
onPress={onCheckmarkPress}>
{checked && <Ionicons name="checkmark" size={18} color="white" />}
</Pressable>
);
}
export default function Anbieter({ route, navigation }) {
//CONSTS WHICH WE GOT FROM THE HOMEPAGE AND DECLARATION
const { latitude, longitude, address } = route.params;
var getLat = latitude;
var getLong = longitude;
var getAddress = JSON.stringify(address);
const [restaurentList, setRestaurentList] = useState()
const [filteredRestaurantList, setFilteredRestaurentList] = useState() // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERED LIST TO DISPLAY
const [currentUsers, setCurrentUsers] = useState()
const [ranges, setRanges] = useState(1)
const [showRange, setShowRange] = useState(false)
const [filters, setFilters] = useState([]) // <-- ADD THIS STATE TO KEEP TRACK OF THE FILTERS SELECTED
const filterList = ["Backware", "Bioprodukte", "Feinkost", "Griechische Spezialitäten"] // <--- CREATE A FILTER ARRAY
const addFilter = (filterIndex) => { // <-- FUNCTION ADD FILTER
setFilters([...filters, filterList[filterIndex]])
}
const removeFilter = (filterIndex) => { // <-- FUNCTION REMOVE FILTER
const index = filters.indexOf(filterList[filterIndex]);
const newFilters = [...filters];
newFilters.splice(index, 1)
setFilters(newFilters)
}
// THIS IS A LIST WHICH DISPLAY ALL RESTAURANTS BY GETTING DATA IN PARAMS IN NAME OF DATA
const ListButton = ({ title, data }) => {
return (
<TouchableOpacity onPress={() => { navigation.navigate('Produktubersicht', { data }) }} style={[styles.itemContainer]}>
<Image source={{ uri: data.anbieterImg }} style={{ width: '90%', marginLeft: '5%', height: 160 }} />
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20 }}>{data.firmenname}</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Adresse:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.adresse}</Text>
</Text>
<Text style={{ fontSize: 16, fontWeight: "bold", marginLeft: 20, width: '90%' }}>Kategorie:
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>{data.kategorie}</Text>
</Text>
</TouchableOpacity>
);
}
// THIS FUNCTION IS USE TO CALL ALL RESTAURANT FROM FIREBASE DATABASE
const getRestaurents = async () => {
let arr = []
// THIS IS FIREBASE API ALL DATA IS COMING FROM FIREBASE
var ar = await firebase.database().ref("/anbieter/").once("child_added", snapshot => {
var obj = snapshot.val();
obj.id = snapshot.key;
arr.push(obj);
});
// ALL DATA OF RESTAURANT IS STORING IN STATE HERE THEN FROM HERE ALL DATA WILL DISPLAY
setRestaurentList(arr)
setFilteredRestaurentList(arr)
}
var users = firebase.auth().currentUser;
useEffect(() => {
// WE CALL GET RESTAURANTS API HERE BECAUSE THIS USEEFFECT JUST CALL ONCE WHEN COMPONENT RENDER
console.log(users, 'users');
getRestaurents()
}, []);
useEffect(() => { // <--- ADD THIS TO UPDATE THE FILTER RESTAURANT LIST EVERY TIME THAT THE FILTER ARRAY CHANGE
const rList = [...restaurentList];
if (filters.length) {
const filteredList = rList.filter(r => {
const toAdd = filters.indexOf(r.category)
if (toAdd !== -1) {
return r
}
})
setFilteredRestaurentList(filteredList)
}else { // <-- IF THERE ARE NO FILTER; RESET TO ORIGINAL LIST
setFilteredRestaurentList(rList)
}
}, [filters]);
return (
<ScrollView>
{/* THIS IS THE PART OF ICON WHERE LOGIN , SIGNOUT , Bestellverlauf AND Warenkorb ICON ARE HERE */}
<View style={styles.container}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginRight: 5, marginVertical: 10 }}>
{users ?
<TouchableOpacity onPress={() => { signOutFunc() }}>
<Entypo name="log-out" size={30} color="black" />
</TouchableOpacity>
: null}
{users ?
<View style={{ flexDirection: 'row', }}>
<TouchableOpacity onPress={() => { navigation.navigate('Bestellverlauf') }} style={{ marginRight: 20 }}>
<Fontisto name="prescription" size={30} color="black" />
</TouchableOpacity>
<TouchableOpacity onPress={() => { navigation.navigate('Warenkorb') }}>
<Feather name="shopping-bag" size={30} color="black" />
</TouchableOpacity>
</View>
:
<TouchableOpacity style={{ flexDirection: 'row' }} onPress={() => { navigation.navigate('Anmelden') }}>
<FontAwesome5 name="user" size={30} color="black" />
<Text style={{ margin: 10 }}>Registration/Login</Text>
</TouchableOpacity>
}
</View>
<Text style={styles.textFirst}>Ermittelte Adresse:</Text>
<View style={{ alignContent: 'center', flexDirection: 'row', width: '90%' }}>
<Text style={{ marginBottom: 15, marginTop: 10, marginHorizontal: 10 }}>{getAddress} </Text>
<TouchableOpacity onPress={() => { setShowRange(!showRange) }}>
<MaterialCommunityIcons name="filter-plus" size={30} color="grey" />
</TouchableOpacity>
</View>
{/* THIS IS RANGE SLIDER FOR SORTING ALL RESTAURANTS */}
{showRange ?
<View>
<View style={{ flexDirection: 'row', justifyContent: "space-between" }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold' }}> Entfernung festlegen!</Text>
<Text style={{ marginLeft: '3%' }}> {Math.round(ranges)} km</Text>
</View>
<Slider maximumValue={100} style={{ width: '90%', marginLeft: '5%', marginTop: 10, }} value={ranges} onValueChange={(e) => setRanges(e)} />
<View style={{ marginTop: 10 }}>
<Text style={{ marginLeft: '3%', fontSize: 14, fontWeight: 'bold', marginBottom: 10, }}>Filterung nach Kategorie</Text>
{filterList.map((filterItem, index) => (
<View
key={index}
style={styles.checkboxContainer}>
<MyCheckbox
addFilter={addFilter} // <-- ADD THIS PROP
removeFilter={removeFilter} // <-- ADD THIS PROP
filterIndex={index} // <-- ADD THIS PROP
/>
<Text style={styles.checkboxLabel}>filterItem</Text>
</View>
))}
<Button title="Filter anwenden..." color='#5271FF'/>
</View>
</View>
: null
}
<Text style={styles.textSecond}>Sie können gerne die Filterfunktion verwenden, indem Sie oben auf den Symbol klicken...</Text>
{filteredRestaurantList && filteredRestaurantList.map((val, i) => {
return <ListButton key={i} title={val.firmenname} data={val} />
})}
</View>
</ScrollView>
);
}

How to rerender item by clicking on it expo js?

I have a flatlist with rendered list of items. I need for each item to change circle to checked-circle on click and go back on second click. I tried to do it with changing item prop isChecked but circle doesn't rerender until I go out of the screen and came back. How may I fix my problem?
Here is my rendering code:
const renderItems = ({ item }) => (
<TouchableOpacity
onPress={() => (item.isChecked = !item.isChecked)}
style={
item.isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height
}
: { flexDirection: 'row', alignItems: 'center', height: word_height }
}
>
<View
style={{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0'
}}
>
{item.isChecked ? (
<Feather name="check-circle" size={25} color="#3D5201" />
) : (
<Feather name="circle" size={25} color="#3D5201" />
)}
</View>
<View style={styles.word_line}>
<View style={{ width: word_width, paddingLeft: 20 }}>
<Text style={{ fontSize: 20 }}>{item.word}</Text>
</View>
<View style={{ width: word_width, paddingLeft: 20 }}>
<Text style={{ fontSize: 20 }}>{item.translation}</Text>
</View>
</View>
</TouchableOpacity>
);
On this line, you are trying to mutate the props variable, so react will not update the component when the props state is mutated.
onPress={() => (item.isChecked = !item.isChecked)}
To do this, create a separate component (based on the name of the renderItems method, I guess it's just a function in the component) and add state to it.
Use useState and the initial state value that was taken from the props initialIsChecked
const Item = ({isMarked, isChecked: initialIsChecked, word, translation}) => {
const [isChecked, setIsChecked] = useState(initialIsChecked);
const handleClick = () => {
setIsChecked((prev) => !prev);
};
return (
<TouchableOpacity
onPress={handleClick}
style={
isMarked
? {
backgroundColor: '#FE2C55',
flexDirection: 'row',
alignItems: 'center',
height: word_height,
}
: {flexDirection: 'row', alignItems: 'center', height: word_height}
}>
<View
style={{
width: 45,
justifyContent: 'center',
alignItems: 'center',
height: '100%',
backgroundColor: '#F6FFE0',
}}>
{isChecked ? (
<Feather name="check-circle" size={25} color="#3D5201" />
) : (
<Feather name="circle" size={25} color="#3D5201" />
)}
</View>
<View style={styles.word_line}>
<View style={{width: word_width, paddingLeft: 20}}>
<Text style={{fontSize: 20}}>{word}</Text>
</View>
<View style={{width: word_width, paddingLeft: 20}}>
<Text style={{fontSize: 20}}>{translation}</Text>
</View>
</View>
</TouchableOpacity>
);
};
Then the list component should look something like this:
const List = () => {
return <ScrollView>
items.map((item) => (
<Item
key={item.id} // if there is id
isMarked={item.isMarked}
isChecked={item.isChecked}
word={item.word}
translation={item.translation}
/>
)
</ScrollView>;
};

How to Pass Props to Modal Component in React Native

I need to pass Flatlist data to modal in react native. Like, on click the item from the flatlist, it shows the modal with data for selected item. Here is my code below
Home.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, FlatList, Image, TouchableOpacity, Alert, Button } from 'react-native';
import { Popup } from './Modal';
import * as productdata from '../data/productdata.js';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
this.setState({
isLoading: false,
dataSource: productdata.product,
})
}
popupRef = React.createRef()
onShowPopup = item => {
popupRef.show();
}
onClosePopup = () => {
popupRef.close()
}
ProductList = ({ item }) => (
<View style={styles.listItem}>
<TouchableOpacity onPress={() => this.onShowPopup(item)} style={{ height: 100, width: 100, justifyContent: "center", alignItems: "center" }}>
<Image source={item.photo} style={{ width: 100, height: 100, borderRadius: 15 }} />
</TouchableOpacity>
<View style={{ alignItems: "center", flex: 1, marginTop: 20 }}>
<Text style={{ fontWeight: "bold", fontSize: 22 }}>{item.name}</Text>
<Text style={{ fontSize: 18, fontWeight: "bold" }}>{item.price}</Text>
</View>
<Popup name="Product Details" ref={(target) => popupRef = target} onTouchOutside={this.onClosePopup} />
</View>
);
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={this.ProductList}
keyExtractor={item => item.name}
/>
</View>
);
}
}
Modal.js
import React, { Component } from 'react';
import { Modal, Dimensions, TouchableWithoutFeedback, StyleSheet, View, Text, Button, Image, TouchableOpacity } from 'react-native';
const deviceHeight = Dimensions.get("window").height
export class Popup extends 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 { name } = this.props
return (
<View style={{ alignItems: 'center' }}>
<Text style={{
color: 'black', fontSize: 20,
fontWeight: 'bold', margin: 15
}}>
{name}
</Text>
</View>
)
}
renderContent = (item) => {
return (
<View style={{ alignItems: 'center', marginBottom: 10 }}>
<View style={styles.card}>
<Text style={{ fontSize: 20, fontWeight: '500', fontWeight: 'bold', alignSelf: 'center', margin: 5 }}/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.button}>Add to Cart</Text>
</TouchableOpacity>
</View>
</View>
)
}
render() {
let { show } = this.state
const { onTouchOutside, title } = this.props
return (
<Modal animationType={'slide'} 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%', height: '70%', borderTopRightRadius:20, borderTopLeftRadius: 20, paddingHorizontal: 20, maxHeight: deviceHeight * 5}}>
{this.renderTitle()}
{this.renderContent()}
</View>
</View>
</Modal>
)
}
}
My Problem: I am not able to pass the flatlist item data to a Modal component and have no better idea solving it in this code.
Please help me and if any including, changes or complete solution for perfect understanding for the requirement would be really great. Many Thanks in Advance!
You don't need to duplicate open state in modal/popup. Simply set the style and open. Assume open close state is controlled by parent component, so if rendering modal/popup it is open by definition.
class Popup extends React.Component {
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 { name } = this.props;
return (
<View style={{ alignItems: 'center' }}>
<Text
style={{
color: 'black',
fontSize: 20,
fontWeight: 'bold',
margin: 15,
}}>
{name}
</Text>
</View>
);
};
renderContent = () => {
const { item } = this.props;
return (
<View style={{ alignItems: 'center', marginBottom: 10 }}>
<View style={styles.card}>
<Text
style={{
fontSize: 20,
fontWeight: '500',
// fontWeight: "bold",
alignSelf: 'center',
margin: 5,
}}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text>Name: {item.name}</Text>
<Text>Price: {item.price}</Text>
<Text>Description: {item.desc}</Text>
<Text>Rating: {item.rating}</Text>
<Text style={styles.button}>Add to Cart</Text>
</TouchableOpacity>
</View>
</View>
);
};
render() {
const { onTouchOutside, title } = this.props;
return (
<Modal
animationType={'slide'}
transparent
visible // <-- visible prop is truthy
onRequestClose={this.close}>
<View
style={{
flex: 1,
backgroundColor: '#000000AA',
justifyContent: 'flex-end',
zIndex: 1000,
}}>
{this.renderOutsideTouchable(onTouchOutside)}
<View
style={{
backgroundColor: '#FFFFFF',
width: '100%',
height: '70%',
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingHorizontal: 20,
maxHeight: deviceHeight * 5,
}}>
{this.renderTitle()}
{this.renderContent()}
</View>
</View>
</Modal>
);
}
}
A react ref isn't necessary for opening a modal/popup to display a specific item. Change the onShowPopup and onClosePopup to set/nullify a clicked on item. Conditionally render the Popup outside the Flatlist.
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: productdata.product,
isLoading: false,
popupItem: null,
};
}
onShowPopup = (popupItem) => {
this.setState({ popupItem });
};
onClosePopup = () => {
this.setState({ popupItem: null });
};
ProductList = ({ item }) => (
<View style={styles.listItem}>
<TouchableOpacity
onPress={() => this.onShowPopup(item)}
style={{
height: 100,
width: 100,
justifyContent: 'center',
alignItems: 'center',
}}>
<Image
source={item.photo}
style={{ width: 100, height: 100, borderRadius: 15 }}
/>
</TouchableOpacity>
<View style={{ alignItems: 'center', flex: 1, marginTop: 20 }}>
<Text style={{ fontWeight: 'bold', fontSize: 22 }}>{item.name}</Text>
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>{item.price}</Text>
</View>
</View>
);
render() {
return (
<View style={styles.container}>
{this.state.popupItem && (
<Popup
name="Product Details"
item={this.state.popupItem} // <-- pass pop item
onTouchOutside={this.onClosePopup}
/>
)}
<FlatList
data={this.state.dataSource}
renderItem={this.ProductList}
keyExtractor={(item) => item.name}
/>
</View>
);
}
}
Expo Snack

react native : there is way to pass a function into "onpress"?

there is way to pass a function into "onpress" ?
i need to pass the "postData" function into the "onpress" button ,
how can i do it?
in my code the has 2 "onpress" that i want to pass inside the "postData" .
if there some mistake so please let me know and i will fix it .
this is my code for example :
export default class OrderInformationScreen extends Component {
constructor(props) {
super(props);
const { state } = props.navigation;
this.state = {
title: state.params.data
}
//alert(JSON.stringify((state.params.data.SHORT_TEXT)))
}
postData = () => {
const postData = {
ACTOR_ID:"APAZ",
REPORT_KEY:"001",
WORK_ITEM_ID:"000018639250",
NOTE:"fun all time"
}
const axios = require('axios')
axios.post('https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApprove_OrderApp_Save_Approvement/'+ postData)
.then(function (response) {
console.log("roei response======>>>>",response);
})
}
render() {
return (
<>
<View
style={{
alignItems: 'flex-start',
justifyContent: 'center',
borderColor: 'blue',
flexDirection: "row",
justifyContent: 'space-evenly'
}}>
<TouchableOpacity onPress={() => console.log("cancel!")}>
<Avatar
size='large'
containerStyle={{ marginTop: 30 }}
activeOpacity={0.2}
rounded
source={require('../assets/down.png')} style={{ height: 80, width: 80 }}
onPress={() => console.log("cancel!")} />
<View >
<Text style={{ fontSize: 25, fontWeight: 'bold', color: 'red' }}>לדחות</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => console.log("works!")}> ///HERE I NEED PASS postData
<Avatar
size='large'
activeOpacity={0.1}
rounded
source={require('../assets/up.png')} style={{ height: 80, width: 80 }}
onPress={() => console.log("Works!")} />
<View>
<Text style={{ fontSize: 25, fontWeight: 'bold', color: 'green', marginHorizontal: 6 }}>לאשר</Text>
</View>
</TouchableOpacity>
</View>
<InfoTable headerInfo={this.state.title}></InfoTable>
</>
);
};
}
Check this updated code
export default class OrderInformationScreen extends Component {
constructor(props) {
super(props);
const { state } = props.navigation;
this.state = {
title: state.params.data
};
//alert(JSON.stringify((state.params.data.SHORT_TEXT)))
}
postData = () => {
const postData = {
ACTOR_ID: "APAZ",
REPORT_KEY: "001",
WORK_ITEM_ID: "000018639250",
NOTE: "fun all time"
};
const axios = require("axios");
axios
.post(
"https://harigotphat1.mekorot.co.il/ConfirmPackaotWS/OrderApprove/OrderApprove_OrderApp_Save_Approvement/" +
postData
)
.then(function(response) {
console.log("roei response======>>>>", response);
});
};
render() {
return (
<>
<View
style={{
alignItems: "flex-start",
justifyContent: "center",
borderColor: "blue",
flexDirection: "row",
justifyContent: "space-evenly"
}}
>
<TouchableOpacity onPress={() => console.log("cancel!")}>
<Avatar
size="large"
containerStyle={{ marginTop: 30 }}
activeOpacity={0.2}
rounded
source={require("../assets/down.png")}
style={{ height: 80, width: 80 }}
onPress={() => console.log("cancel!")}
/>
<View>
<Text style={{ fontSize: 25, fontWeight: "bold", color: "red" }}>
לדחות
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.postData()}>
<Avatar
size="large"
activeOpacity={0.1}
rounded
source={require("../assets/up.png")}
style={{ height: 80, width: 80 }}
onPress={() => console.log("Works!")}
/>
<View>
<Text
style={{
fontSize: 25,
fontWeight: "bold",
color: "green",
marginHorizontal: 6
}}
>
לאשר
</Text>
</View>
</TouchableOpacity>
</View>
<InfoTable headerInfo={this.state.title}></InfoTable>
</>
);
}
}
Simply you can put function like this way
<TouchableOpacity onPress={() => this.postData()}> .... </TouchableOpacity>

How to pass changing state prop to component?

I have a state object called isEdit.
And I have a list of StyledLessons (a component with functionallity that should differ if its in Edit Mode or not).
<StyledLesson title={title} subjectName={subjectName} subtitle={subtitle} isEdit={this.state.isEdit}/>
It's working fine with the default state (so I do see the expected result in the beginning if isEdit is true or false as expected) but the content doesn't change if I change my state in the parent object.
Any ideas how I could manage the child component to change on the fly?
Here is how I change my state:
this.state.isEdit ?
<Icon
name='check'
color={Colors.tabBarText}
onPress={() => this.setState({isEdit: false})}
/>
:
<Icon
name='edit'
color={Colors.tabBarText}
onPress={() => this.setState({isEdit: true})}
/>
Code of the child component:
class StyledLesson extends React.PureComponent {
constructor(props) {
super(props);
this.isEdit = props.isEdit??true;
this.state = {expanded: false};
}
getEditableView() {
return (
<View style={{flexDirection: 'row', flex: 1, alignItems: 'center', marginHorizontal: 10}}>
<TouchableOpacity>
<Icon
name={'remove-circle'}
color={'#f00'}
/>
</TouchableOpacity>
<TouchableOpacity style={{flex: 1}}>
<FlatCard>
<Text style={{color: '#666', fontSize: 18}}>{this.props.title}</Text>
<Text
style={{
fontWeight: 'bold',
fontSize: 35,
color: Colors.textColor
}}>{this.props.subjectName}</Text>
<Text style={{color: '#666', fontSize: 18}}>{this.props.subtitle}</Text>
</FlatCard>
</TouchableOpacity>
</View>
);
}
getDisplayView() {
return (
//Normal View
<View style={{flexDirection: 'row', flex: 1, alignItems: 'center', marginHorizontal: 10}}>
<TouchableOpacity
onPress={
() => {
this.setState({expanded: !this.state.expanded});
}
}
style={{flex: 1}}
>
<FlatCard>
{this.state.expanded &&
<Text style={{color: '#666', fontSize: 18}}>{this.props.title}</Text>
}
<Text
style={{
fontWeight: 'bold',
fontSize: 35,
color: Colors.textColor
}}>{this.props.subjectName}</Text>
{this.state.expanded &&
<Text style={{color: '#666', fontSize: 18}}>{this.props.subtitle}</Text>
}
</FlatCard>
</TouchableOpacity>
</View>
);
}
render() {
return (
this.isEdit ? this.getEditableView() : this.getDisplayView()
);
}
}
export default StyledLesson;
this.isEdit = props.isEdit??true;
This is the issue. You are updating this property only inside the constructor. Event if the props value is changing, the property won't.
You can try to modify your render method to something like
render() {
return (
(this.props.isEdit??true) ? this.getEditableView() : this.getDisplayView()
);
}

Categories

Resources