I have am making a form in React Native (testing on IOS/Expo go) and for reasons that I cannot pinpoint, my TouchableWithoutFeedback's onPress event is not firing at all.
I made sure to wrap the TouchableWithoutFeedback's children in a single View component (as suggested by other answers on github and stack overflow), but the problem persists.
import React from 'react';
import {TouchableWithoutFeedback, Dimensions, StyleSheet, ScrollView, Keyboard, Text, View, Image, SafeAreaView, Button , Pressable, TextInput, FlatList} from 'react-native';
import Header from './Header';
import { createNativeStackNavigator} from '#react-navigation/native-stack';
import { useNavigation, useRoute } from '#react-navigation/native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import constants from './constants';
import Icon from 'react-native-vector-icons/Feather';
export default function NewMemory(){
const [dateShow, setDateShow] = React.useState(false);
const [timeShow, setTimeShow] = React.useState(false);
const [date, setDate] = React.useState('');
const [time, setTime] = React.useState('');
function setDateWrapper(date){
console.log(date.toLocaleDateString());
setDate(date.toLocaleDateString());
setDateShow(false);
}
function setTimeWrapper(time){
time = time.toLocaleTimeString();
let tokens = time.split(':');
let ampm = tokens[tokens.length-1];
ampm = ampm.split(' ')[1];
tokens[2] = ampm;
setTime(tokens[0] + ':' + tokens[1] + ' ' + ampm);
setTimeShow(false);
}
return (
<View style={{width: '100%', /* borderColor:'green', borderWidth: 1 */}}>
<Header title='Send Capsule' backButton></Header>
<View style={{borderBottomColor:'grey', borderBottomWidth:1, display:'flex', flexDirection:'row', padding: 10}}>
<Icon name='image' size={70}></Icon>
<TouchableWithoutFeedback onPress={()=> {console.log('this message should appear on screen tap, but doesnt'); Keyboard.dismiss()}}>
<View style={{flex: 1, borderWidth: 3, borderColor: 'red'}}>
<TextInput
multiline
placeholder='Write a caption...'
style={{ flex: 1, padding:10, paddingTop: 12, paddingBottom: 12}}
maxHeight={240}
></TextInput>
</View>
</TouchableWithoutFeedback>
</View>
<View style={{ padding: 10}}>
<View>
<Text style={{marginBottom:5}}>Unlock Date</Text>
<Pressable onPress={()=>setDateShow(true)} style={{display: 'flex', flexDirection: 'row', alignItems:'center', padding: 10, borderRadius:5, backgroundColor: constants.inputFieldGreyBackground}}>
<Text style={date? null : {color: '#b5b5b5'}}>{date ? date : 'Date'}</Text>
</Pressable>
</View>
<View style={{height:10}}></View>
<Pressable onPress={()=>setTimeShow(true)} style={{display: 'flex', flexDirection: 'row', alignItems:'center', padding: 10, borderRadius:5, backgroundColor: constants.inputFieldGreyBackground}}>
<Text style={time? null : {color: '#b5b5b5'}}>{time ? time : 'Time (optional)'}</Text>
</Pressable>
<DateTimePickerModal isVisible={dateShow} display='spinner' mode='date' onCancel={()=>setDateShow(false)} onConfirm={(date)=> {setDateWrapper(date)}}></DateTimePickerModal>
<DateTimePickerModal isVisible={timeShow} display='spinner' mode='time' onCancel={()=>setTimeShow(false)} onConfirm={(time)=> {setTimeWrapper(time)}}></DateTimePickerModal>
</View>
</View>
);
}
Is there a reason why you must use "ToucheableWithoutFeedback"? I'd recommend you to use "Pressable" instead as suggested by official React Native docs on ToucheableWithoutFeedback.
React Native official documentation on ToucheableWithoutFeedback:
Do not use unless you have a very good reason.
There's two ways you can fix the issue.
1. Continue using ToucheableWithoutFeedback
You'll have to follow the documentation on how it should be used.
Note that you need to add {...props} in the <View /> component.
Importantly, TouchableWithoutFeedback works by cloning its child and
applying responder props to it. It is therefore required that any
intermediary components pass through those props to the underlying
React Native component. (From react native docs)
<TouchableWithoutFeedback onPress={()=> {console.log('hello'); Keyboard.dismiss()}}>
<View {...props} style={{flex: 1, borderWidth: 3, borderColor: 'red'}}>
<TextInput
multiline
placeholder='Write a caption...'
style={{ flex: 1, padding:10, paddingTop: 12, paddingBottom: 12}}
maxHeight={240}
/>
</View>
</TouchableWithoutFeedback>
2. Change ToucheableWithoutFeedback to Pressable.
Note that you don't need to pass {...props}.
<Pressable onPress={()=> {console.log('hello'); Keyboard.dismiss()}}>
<View style={{flex: 1, borderWidth: 3, borderColor: 'red'}}>
<TextInput
multiline
placeholder='Write a caption...'
style={{ flex: 1, padding:10, paddingTop: 12, paddingBottom: 12}}
maxHeight={240}
/>
</View>
</Pressable>
import React from 'react';
import {TouchableWithoutFeedback, Dimensions, StyleSheet, ScrollView, Keyboard, Text, View, Image, SafeAreaView, Button , Pressable, TextInput, FlatList,} from 'react-native';
import { createNativeStackNavigator} from '#react-navigation/native-stack';
import { useNavigation, useRoute } from '#react-navigation/native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import Icon from 'react-native-vector-icons/Feather';
export default function App(){
const [dateShow, setDateShow] = React.useState(false);
const [timeShow, setTimeShow] = React.useState(false);
const [date, setDate] = React.useState('');
const [time, setTime] = React.useState('');
function setDateWrapper(date){
console.log(date.toLocaleDateString());
setDate(date.toLocaleDateString());
setDateShow(false);
}
function setTimeWrapper(time){
time = time.toLocaleTimeString();
let tokens = time.split(':');
let ampm = tokens[tokens.length-1];
ampm = ampm.split(' ')[1];
tokens[2] = ampm;
setTime(tokens[0] + ':' + tokens[1] + ' ' + ampm);
setTimeShow(false);
}
return (
<View style={{width: '100%', /* borderColor:'green', borderWidth: 1 */}}>
<View style={{borderBottomColor:'grey', borderBottomWidth:1, display:'flex', flexDirection:'row', padding: 10}}>
<Icon name='image' size={70}></Icon>
<TouchableWithoutFeedback onPress={()=> {console.log('hello'); Keyboard.dismiss()}}>
<View style={{flex: 1, borderWidth: 3, borderColor: 'red'}}>
<TextInput
multiline
placeholder='Write a caption...'
style={{ flex: 1, padding:10, paddingTop: 12, paddingBottom: 12}}
maxHeight={240}
></TextInput>
</View>
</TouchableWithoutFeedback>
</View>
<View style={{ padding: 10}}>
<View>
<Text style={{marginBottom:5}}>Unlock Date</Text>
<Pressable onPress={()=>setDateShow(true)} style={{display: 'flex', flexDirection: 'row', alignItems:'center', padding: 10, borderRadius:5, }}>
<Text style={date? null : {color: '#b5b5b5'}}>{date ? date : 'Date'}</Text>
</Pressable>
</View>
<View style={{height:10}}></View>
<Pressable onPress={()=>setTimeShow(true)} style={{display: 'flex', flexDirection: 'row', alignItems:'center', padding: 10, borderRadius:5, }}>
<Text style={time? null : {color: '#b5b5b5'}}>{time ? time : 'Time (optional)'}</Text>
</Pressable>
<DateTimePickerModal isVisible={dateShow} display='spinner' mode='date' onCancel={()=>setDateShow(false)} onConfirm={(date)=> {setDateWrapper(date)}}></DateTimePickerModal>
<DateTimePickerModal isVisible={timeShow} display='spinner' mode='time' onCancel={()=>setTimeShow(false)} onConfirm={(time)=> {setTimeWrapper(time)}}></DateTimePickerModal>
</View>
</View>
);
}
Related
I was trying to navigate cross different screens on button click in React Native. Following is the code:
App.tsx
import React from "react";
import { StyleSheet, View, Text} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Login from './src/screens/Login/login'
import SignUp from './src/screens/SignUp/signUp'
import { getItem } from './src/utility/AsyncStorage'
export default function App() {
const [gmailId, setGmailId] = React.useState("");
const [password, setPassword] = React.useState("");
React.useEffect(() => {
getItem("gmailId").then((value:any) => {setGmailId(value)});
getItem("password").then((value:any) => {setPassword(value)});
}, []);
const RootStack = createNativeStackNavigator();
return (
<View style={styles.container}>
<NavigationContainer>
<RootStack.Navigator initialRouteName="Login">
<RootStack.Screen name="Login" component={Login} />
<RootStack.Screen name="signup" component={SignUp} />
</RootStack.Navigator>
</NavigationContainer>
{/* {(!gmailId && !password)? <Login/>: <Text>Logged In</Text>} */}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
});
login.tsx
import React from "react";
import { Text, View, Image, TextInput, TouchableOpacity} from 'react-native';
import { SocialIcon } from 'react-native-elements'
import { loginStyle } from './loginStyle'
import { signIn } from './loginLogic'
const Login = (navigation:any) => {
const [gmailId, setGmailId] = React.useState("");
const [password, setPassword] = React.useState("");
const navigateToSignUp = () => {
navigation.navigate('signup')
};
return (
<View style={styles.container}>
<Image
style={styles.tinyLogo}
source={require( "../../../assets/icon.png")}
/>
<View style={{ width: '100%', alignItems: 'center', justifyContent: 'center', marginTop: 30}}>
<TextInput
style={styles.input}
placeholder="Enter Gmail Id"
onChangeText={setGmailId}
/>
<TextInput
style={styles.input}
onChangeText={setPassword}
placeholder="Enter your Password"
secureTextEntry={true}
/>
<TouchableOpacity
style={[styles.button, styles.loginButton]}
onPress={()=>signIn(gmailId, password)}>
<Text style={styles.text}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.signupButton]}
onPress={() => navigateToSignUp}>
<Text style={styles.text}>Create New Account</Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', width: '95%', margin: 10, marginTop: 25}}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 100, textAlign: 'center'}}>Social Login</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
<SocialIcon
style={{width:"85%"}}
title='Sign In With Google'
button
type='google'
onPress={()=>{console.log('Sign In With Google')}}
/>
</View>
)
}
export default Login
//===================== STYLE SECTION =====================
const styles = loginStyle()
SignUp.tsx
import { StyleSheet, Text, View } from 'react-native'
import React from 'react'
const SignUp = () => {
return (
<View>
<Text>signUp</Text>
</View>
)
}
export default SignUp
const styles = StyleSheet.create({})
My coding is not throwing any error yet none of the screens are visible (Not even the initialRoute). On running the code, it shows up a White page only.
Please help me rectify the issue.
import React from "react";
import { Text, View, Image, TextInput, TouchableOpacity} from 'react-native';
import { SocialIcon } from 'react-native-elements'
import { loginStyle } from './loginStyle'
import { signIn } from './loginLogic'
const Login = ({navigation:any}) => {
const [gmailId, setGmailId] = React.useState("");
const [password, setPassword] = React.useState("");
const navigateToSignUp = () => {
navigation.navigate('signup')
};
return (
<View style={styles.container}>
<Image
style={styles.tinyLogo}
source={require( "../../../assets/icon.png")}
/>
<View style={{ width: '100%', alignItems: 'center', justifyContent: 'center', marginTop: 30}}>
<TextInput
style={styles.input}
placeholder="Enter Gmail Id"
onChangeText={setGmailId}
/>
<TextInput
style={styles.input}
onChangeText={setPassword}
placeholder="Enter your Password"
secureTextEntry={true}
/>
<TouchableOpacity
style={[styles.button, styles.loginButton]}
onPress={()=>signIn(gmailId, password)}>
<Text style={styles.text}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.signupButton]}
onPress={() => navigateToSignUp}>
<Text style={styles.text}>Create New Account</Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', width: '95%', margin: 10, marginTop: 25}}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 100, textAlign: 'center'}}>Social Login</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
<SocialIcon
style={{width:"85%"}}
title='Sign In With Google'
button
type='google'
onPress={()=>{console.log('Sign In With Google')}}
/>
</View>
)
}
export default Login
please try it.
or
import React from "react";
import { Text, View, Image, TextInput, TouchableOpacity} from 'react-native';
import { SocialIcon } from 'react-native-elements'
import { loginStyle } from './loginStyle'
import { signIn } from './loginLogic'
const Login = (props:any) => {
const [gmailId, setGmailId] = React.useState("");
const [password, setPassword] = React.useState("");
const navigateToSignUp = () => {
props.navigation.navigate('signup')
};
return (
<View style={styles.container}>
<Image
style={styles.tinyLogo}
source={require( "../../../assets/icon.png")}
/>
<View style={{ width: '100%', alignItems: 'center', justifyContent: 'center', marginTop: 30}}>
<TextInput
style={styles.input}
placeholder="Enter Gmail Id"
onChangeText={setGmailId}
/>
<TextInput
style={styles.input}
onChangeText={setPassword}
placeholder="Enter your Password"
secureTextEntry={true}
/>
<TouchableOpacity
style={[styles.button, styles.loginButton]}
onPress={()=>signIn(gmailId, password)}>
<Text style={styles.text}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.signupButton]}
onPress={() => navigateToSignUp}>
<Text style={styles.text}>Create New Account</Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', width: '95%', margin: 10, marginTop: 25}}>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
<View>
<Text style={{width: 100, textAlign: 'center'}}>Social Login</Text>
</View>
<View style={{flex: 1, height: 1, backgroundColor: 'black'}} />
</View>
<SocialIcon
style={{width:"85%"}}
title='Sign In With Google'
button
type='google'
onPress={()=>{console.log('Sign In With Google')}}
/>
</View>
)
}
export default Login
this one surely help you
thanks
whenever i click on textinput , key board appears and disappears, i also tried on other android device as well
import React, { useState } from 'react';
import {SafeAreaView,Image,StyleSheet,FlatList,View,Text,Button,TextInput,StatusBar,ScrollView,TouchableOpacity,Dimensions,}
from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import ForgotScreen from './ForgotScreen';
const {width, height} = Dimensions.get('window');
const Login = ({navigation}) => {
const [email , setEmail]= useState('')
return (
<SafeAreaView style={{flex: 1 , backgroundColor:'white'}}>
<StatusBar backgroundColor={'white'} barStyle="dark-content" />
<View style={{flex:0.5 ,alignItems:'center', justifyContent:'center'}}>
<Text style={{fontWeight:'bold' , color:'black',fontSize:20 ,margin:50}}>Login</Text>
**<TextInput placeholder='Email' placeholderTextColor={'grey'} style={styles.input_text} value={email} onChangeText={setEmail}/>
<TextInput placeholder='Password' placeholderTextColor={'grey'} style={styles.input_text}/>**
<TouchableOpacity style={{justifyContent:'center' , width:'90%' }} onPress={() => navigation.navigate('ForgotScreen')}>
<Text style={{color:'#A2D5AB' , alignSelf:'flex-end',marginVertical:15 , justifyContent:'center'}}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn}>
<Text style={{color:'white'}} onPress={() => navigation.navigate('HomeScreen')}>Login</Text>
</TouchableOpacity>
</View>
<View style={{flex:0.5 ,alignItems:'center', justifyContent:'center'}}>
<TouchableOpacity>
<Text style={{color:'#A2D5AB' , alignSelf:'baseline' , justifyContent:'center' , marginTop:200}} onPress={() => navigation.navigate('SignUp')}>Sign up an account</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles=StyleSheet.create({
input_text:{
width:'90%',
height:50,
color:'black',
borderRadius:10,
borderBottomWidth:1,
borderColor:'grey',
},
btn: {
width:'90%',
shadowColor:"black",
shadowOpacity:0.8,
elevation:3,
shadowRadius:15,
height: 50,
marginHorizontal:10,
borderRadius: 5,
backgroundColor: 'gold',
justifyContent: 'center',
alignItems: 'center',
},
})
export default Login;
How do I pass FlatList items to another screen that also have a FlatList?
I'm using React Navigation V5 to pass the FlatList item to the other screen. Thats working fine. I can see the text when only using ´<Text.>{details.id}</Text .>´ but not when trying to pass it to FlatList, then there is nothing.
CODE
import React, { useState } from 'react';
import {
View,
TextInput,
FlatList,
Text,
TouchableOpacity,
Linking,
Modal,
ScrollView,
} from 'react-native';
import { useTheme } from '../Data/ThemeContext';
import DataBase from '../Data/DataBase';
import Octicons from 'react-native-vector-icons/Octicons';
export default function Home({ navigation }) {
const [search, setSearch] = useState('');
const [masterDataSource, setMasterDataSource] = useState(DataBase);
const [modalVisible, setModalVisible] = useState(false);
const [details, setDetails] = useState('');
const { colors } = useTheme();
const filteredDataSource = masterDataSource.filter((item) => {
return (
item.name.includes(search) ||
(item.id && item.id.includes(search)) ||
(item.gluten && item.gluten.includes(search)) ||
(item.company && item.company.includes(search))
);
});
const itemSeparatorComponent = () => {
return (
<View
style={{
margin: 3,
}}></View>
);
};
const emptyComponent = () => {
return (
<View style={{ alignItems: 'center' }}>
<Text style={{ color: colors.text }}>Finns inte produkten med?</Text>
<View style={{ marginTop: 30 }}>
<TouchableOpacity
onPress={() => Linking.openURL('')}>
<Text
style={{
color: colors.text,
borderWidth: 1,
borderColor: colors.text,
padding: 10,
borderRadius: 5,
backgroundColor: colors.card,
}}>
KONTAKTA OSS
</Text>
</TouchableOpacity>
</View>
</View>
);
};
const renderItem = ({ item }) => {
return (
<View>
<TouchableOpacity
style={{
marginLeft: 20,
marginRight: 20,
elevation: 3,
backgroundColor: colors.card,
borderRadius: 10,
}}
onPress={() => {
setModalVisible(true);
setDetails(item);
}}>
<View style={{ margin: 10 }}>
<Text style={{ color: colors.text }}>{item.company}</Text>
<Text style={{ color: colors.text, fontWeight: '700' }}>
{item.name}
</Text>
<Text style={{ color: colors.text }}>{item.gluten}</Text>
<Text style={{ color: colors.text }}>{item.id}</Text>
</View>
</TouchableOpacity>
</View>
);
};
return (
<View style={{ flex: 1, backgroundColor: colors.background }}>
<Modal
animationType="none"
hardwareAccelerated={true}
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.8)',
}}>
<View
style={{
backgroundColor: colors.Modal,
padding: 35,
borderRadius: 10,
width: '80%',
height: '80%',
}}>
<ScrollView showsVerticalScrollIndicator={false}>
<View style={{ marginTop: 20 }}>
<Text style={{ color: colors.text }}>{details.company}</Text>
<Text
style={{ color: colors.text, marginTop: 20, fontSize: 20 }}>
{details.name}
</Text>
<Text style={{ color: colors.text, marginTop: 20 }}>
{details.gluten}
</Text>
<Text style={{ color: colors.text, marginTop: 20 }}>
Ingredienser
</Text>
<Text style={{ color: colors.text, marginTop: 2 }}>
{details.ingredients}
</Text>
<Text style={{ color: colors.text, marginTop: 30 }}>
{details.id}
</Text>
</View>
</ScrollView>
<View
style={{
borderTopWidth: 1,
borderTopColor: colors.text,
marginBottom: 10,
}}></View>
<View
style={{ flexDirection: 'row', justifyContent: 'space-evenly' }}>
<TouchableOpacity
onPress={() => {
const updated = [...masterDataSource];
updated.find(
(item) => item.id === details.id,
).selected = true;
setMasterDataSource(updated);
navigation.navigate('Inköpslista', {
items: updated.filter((item) => item.selected),
});
}}>
<Text>Lägg i Inköpslistan</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
setModalVisible(false);
}}>
<Text style={{ alignSelf: 'center', color: '#FF0000' }}>
Stäng
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: colors.Textinput,
elevation: 12,
}}>
<TextInput
style={{
flex: 1,
backgroundColor: '#fff',
borderTopLeftRadius: 5,
borderBottomLeftRadius: 5,
}}
placeholder=" SÖK PRODUKT NAMN / STRECKKOD"
placeholderTextColor="#000"
onChangeText={(text) => setSearch(text)}
value={search}
autoCapitalize="words"
/>
<Octicons
style={{
marginLeft: 1,
padding: 13,
backgroundColor: '#fff',
height: 49,
borderTopRightRadius: 5,
borderBottomRightRadius: 5,
}}
name="checklist"
size={25}
color="#000"
onPress={() =>
navigation.navigate('Inköpslista', {
items: masterDataSource.filter((item) => item.selected),
})
}
/>
</View>
<View style={{ flex: 1, marginTop: 20 }}>
<FlatList
data={filteredDataSource}
ItemSeparatorComponent={itemSeparatorComponent}
keyExtractor={(_, index) => index.toString()}
renderItem={renderItem}
initialNumToRender={4}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
updateCellsBatchingPeriod={100}
showsVerticalScrollIndicator={true}
ListEmptyComponent={emptyComponent}
contentContainerStyle={{ paddingBottom: 20 }}
/>
</View>
</View>
);
}
SECOND SCREEN
import React from 'react';
import { View, Text, FlatList, Button } from 'react-native';
export default function ShoppingList({ route, navigation }) {
const RenderItem = ({ item }) => {
return (
<TouchableOpacity
style={{ marginHorizontal: 10, marginVertical: 15 }}
onPress={() => {}}>
<Text>{item.id}</Text>
<Text>{item.name}</Text>
</TouchableOpacity>
);
};
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginTop: 30,
}}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<FlatList
data={route.params && route.params.items}
renderItem={RenderItem}
/>
</View>
);
}
Based on your question, this is the flow that you want
User has flat list with a set of items
When an item is clicked a modal is opened
If the user wants he clicks 'Add to cart' which will add item to cart and open cart.
When cart is opened user is shown a flatlist with the selected items.
Screen 1 : Home
Here you already have a modal but you pass a single item instead of an array.
So the better way is to use the masterDataSource state that you have and add a 'selected' property to it.
So the button in the Modal would be like this
<Button
title="Add and View Cart"
onPress={() => {
const updated = [...masterDataSource];
updated.find((item) => item.id === details.id).selected = true;
setMasterDataSource(updated);
navigation.navigate('Cart', {
items: updated.filter((item) => item.selected),
});
}}
/>
Once you click the Button you would be taken to the cart page with the items array which you have selected (This will have the previous items as well).
The Cart screen will have a Flatlist to show the items that are passed via params like below. RenderItem can be the code for your item.
<FlatList
data={route.params && route.params.items}
renderItem={RenderItem}
/>
You can run the sample below
https://snack.expo.io/#guruparan/cartexample
(Modal doesnt work properly on web you can try the android version)
According to React Native Docs, the prop data on FlatList should contain an Array, like this [{...}] or this [{...},{...},{...}...]. But you are trying to pass an Object to the FlatList on the ShoppingList screen, like this {...}.
On ShoppingList Screen when you're destructuring like the following
const { details } = route.params;
You are creating an object, which looks like this {...}
So you need to convert it to an array. Use the following code snippet
const itemInfo = []
itemInfo.push(details)
Now just pass itemInfo to data prop of FlatList.
Your ShoppingList screen should look like this.
import React from 'react';
import {
View,
FlatList,
Text,
} from 'react-native';
export default function ShoppingList({ route }) {
const { details } = route.params;
const itemInfo = [];
itemInfo.push(details);
return (
<View style={{ flex: 1, backgroundColor: "white" }}>
<FlatList
data={itemInfo}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View>
<Text style={{ color: "black" }}>{item.company}</Text>
<Text style={{ color: "black" }}>{item.name}</Text>
<Text style={{ color: "black" }}>{item.gluten}</Text>
<Text style={{ color: "black" }}>{item.id}</Text>
</View>
)}
/>
</View>
);
}
I am making a react native app and for some reason when I tap on the text input to type something it disappears under the keyboard. I want it to come to the top of the keyboard like the way Instagram messenger and other messenger apps do it. I tried using keyboardAvoidView and setting the behavior to padding and height but none of it worked.
import {
View,
Text,
StyleSheet,
SafeAreaView,
TextInput,
TouchableOpacity,
} from "react-native";
import CommunityPost from "../components/CommunityPost";
import { Context as CommunityContext } from "../context/CommunityContext";
const Key = ({ navigation }) => {
const { createCommunityPost, errorMessage } = useContext(CommunityContext);
const [body, setBody] = useState("");
return (
<View style={styles.container}>
<SafeAreaView />
<CommunityPost />
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
multiline={true}
placeholder="Type..."
placeholderTextColor="#CACACA"
value={body}
onChangeText={setBody}
/>
<TouchableOpacity
style={{ justifyContent: "center", flex: 1, flexDirection: "row" }}
onPress={() => createCommunityPost({ body })}
>
<Text style={styles.sendText}>Send</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "flex-start",
backgroundColor: "#2B3654",
justifyContent: "flex-end",
},
inputContainer: {
justifyContent: "flex-end",
flexDirection: "row",
},
sendText: {
color: "white",
fontSize: 25,
},
input: {
fontSize: 25,
color: "white",
borderColor: "#2882D8",
borderWidth: 1,
borderRadius: 15,
width: "80%",
marginBottom: 30,
marginLeft: 10,
padding: 10,
},
});
export default Key;
You must KeyboardAvoidingView component provided by react native.
<KeyboardAvoidingView
behavior={Platform.OS == "ios" ? "padding" : "height"}
style={styles.container}
>
<SafeAreaView />
<CommunityPost />
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
multiline={true}
placeholder="Type..."
placeholderTextColor="#CACACA"
value={body}
onChangeText={setBody}
/>
<TouchableOpacity
style={{ justifyContent: "center", flex: 1, flexDirection: "row" }}
onPress={() => createCommunityPost({ body })}
>
<Text style={styles.sendText}>Send</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
For these situations we can use one of these methods:
1.wrapping Component with <ScrollView></ScrollView>
2.wrapping Component with <KeyboardAvoidingView></KeyboardAvoidingView>
Sometimes our wrong given styles can make these happens too such as : Having a fixed value for our styles, check your margins and use one of the given methods
I hope it helps
Try using keyboardVerticalOffset and test it with different values.
For more info check this out
For those who want to keep the code clean, just use the FlatList component and add a View component involving the component with the states: {flex: 1, height: Dimensions.get ("window"). Height}.
Below left a component ready for anyone who wants to use, just wrap your component in this way:
<FormLayout>
{... your component}
</FormLayout>
Here is the solver component:
import React from 'react'
import { View, StyleSheet, FlatList, Dimensions } from 'react-native'
import Background from './Background'
const FormLayout = ({ children }) => {
const renderContent = <View style={styles.container}>
{children}
</View>
return <FlatList
ListHeaderComponent={renderContent}
showsVerticalScrollIndicator={false}
/>
}
const styles = StyleSheet.create({
container: {
flex: 1,
height: Dimensions.get('window').height * 0.95
}
})
export default FormLayout
I was trying to make a "photo galley app" where each image is a "button" that toggle on the boolean property for Modal tag. The problem is that the images are rendered by a FlatList which pass props to component "GenerateImage.js", but at the same time, I need to pass the state and dispatch function as a parameter as well.
File who render the FlatList:
import React, { Component } from 'react'
import { FlatList, View, StyleSheet, TouchableOpacity, Text, AppRegistry } from 'react-native'
import { connect } from 'react-redux'
import GenerateImage from '../components/GenerateImage'
import commonStyles from '../commonStyles'
import Modal from '../components/Modal'
const Photos = ({ params }) => {
return (
<View style={{ flex: 1 }}>
<Modal isVisible={params.showFullImage} />
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Hoje</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Mês</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Ano</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchContainer}>
<Text style={styles.button}>Álbuns</Text>
</TouchableOpacity>
</View>
<View style={{ flex: 30 }}>
<FlatList data={params.images} keyExtractor={item => `${item.id}`}
renderItem={({item}) => <GenerateImage {...item} />} numColumns={2} />
</View>
</View>
)
}
const styles = StyleSheet.create({
buttonsContainer: {
flex: 3,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#1c2431',
},
touchContainer: {
marginHorizontal: 20,
backgroundColor: '#439ce8',
borderRadius: 30,
width: 65,
alignItems: 'center',
justifyContent: 'center',
padding: 5
},
button: {
color: 'white',
fontFamily: commonStyles.Font,
fontSize: 14
}
})
export default connect(state => ({ params: state[0] }))(Photos)
GenerateImage.js:
import React from 'react'
import { View,
StyleSheet,
Image,
PixelRatio,
Dimensions,
TouchableOpacity } from 'react-native'
import { connect } from 'react-redux'
const GenerateImage = (props, {param, dispatch}) => {
function toggleModal(param) {
return {
type: 'TOGGLE_MODAL_ON',
}
}
return (
<View style={styles.container}>
<View style={styles.imgContainer}>
<TouchableOpacity activeOpacity={0.7} onPress={() => dispatch(toggleModal(param))}>
<Image source={props.image} style={styles.imgContainer} />
</TouchableOpacity>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginVertical: 5,
marginHorizontal: 4
},
imgContainer: {
height: Dimensions.get('window').height * 0.25,
width: Dimensions.get('window').width * 0.48,
//borderRadius: 8,
//flex: 1,
//orderWidth: 1,
},
image: {
resizeMode: 'contain',
aspectRatio: PixelRatio.get()
},
})
export default connect(state => ({ param: state[0].showFullImage }))(GenerateImage)
So, how can I pass both data?