flatlist slow performance on large data react native - react-native

I'm new to react native and I'm having some performance problem with flatlist in React Native Expo. On my screen I'm displaying a list of contacts and I want them to be selected or deselected and I have managed to achieve that part but the problem is that it takes a lot of visibility time to check the contacts or to uncheck them. Making the screen not very user friendly. I have tried a lot of solutions that I've found on internet regarding this problem but none of them had worked. Hope someone can help me. Below I'll attach the code!
function ContactList() {
const [itemChecked, setItemChecked] = useState([]);
const [checked, setChecked] = useState(false);
const [contacts, setContacts] = useState([]);
const [filter, setFilter] = useState([]);
const [search, setSearch] = useState('');
const [checkedBox, setCheckedBox] = useState(false);
useEffect(() => {
(async () => {
const { status } = await Contacts.requestPermissionsAsync();
if (status === 'granted') {
const { data } = await Contacts.getContactsAsync({
fields: [Contacts.Fields.PhoneNumbers],
// fields: [Contacts.Fields.Name],
});
if (data.length > 0) {
setContacts(data);
setFilter(data);
// console.log('contact', contacts[1]);
// console.log('filter', filter);
}
}
})();
}, []);
const searchFilter = (text) => {
if (text) {
const newData = contacts.filter((item) => {
const itemData = item.name ? item.name.toUpperCase() : ''.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setFilter(newData);
setSearch(text);
} else {
setFilter(contacts);
setSearch(text);
}
};
const onChangeValue = (item, index) => {
if (itemChecked.includes(item.phoneNumbers[0].digits)) {
itemChecked.splice(itemChecked.indexOf(item.phoneNumbers[0].digits), 1);
} else {
itemChecked.push(item.phoneNumbers[0].digits);
setCheckedBox(true);
}
setItemChecked(itemChecked);
console.log(itemChecked);
// console.log(item);
};
const renderItem = ({ item, index }) => {
return (
<SafeAreaView>
<ScrollView>
<TouchableOpacity style={{ flexDirection: 'row', flex: 1 }}>
<View style={{ flex: 1, borderTopWidth: 0.5, borderTopColor: 'grey', marginBottom: 15 }}>
<Text onPress={() => setChecked(true)} style={{ fontSize: 20, marginHorizontal: 10 }}>
{item.name + ' '}
</Text>
<Text style={{ fontSize: 17, marginHorizontal: 10, marginTop: 5, color: 'grey' }}>
{item.phoneNumbers && item.phoneNumbers[0] && item.phoneNumbers[0].number}
</Text>
</View>
<View style={{ flex: 1, borderTopWidth: 0.5, borderTopColor: 'grey' }}>
{itemChecked.includes(item.phoneNumbers[0].digits) === false ? (
<CheckBox
style={{ width: 15, height: 15 }}
right={true}
checked={false}
onPress={() => {
onChangeValue(item, index);
}}
/>
) : (
<CheckBox
style={{ width: 15, height: 15, paddingTop: 8 }}
right={true}
checked={true}
onPress={() => {
onChangeValue(item, index);
}}
/>
)}
</View>
{/* <Post postJson={item} isGroupAdmin={isGroupAdmin} user={user} /> */}
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<View
style={{
height: 40,
justifyContent: 'center',
backgroundColor: '#eeeeee',
width: '90%',
marginHorizontal: 20,
marginTop: 15,
borderRadius: 10,
}}
>
<Feather name="search" size={20} color="grey" style={{ position: 'absolute', left: 32 }} />
<TextInput
placeholder="Search"
placeholderTextColor="#949494"
style={{
left: 20,
paddingHorizontal: 35,
fontSize: 20,
}}
value={search}
onChangeText={(text) => {
searchFilter(text);
setSearch(text);
}}
/>
</View>
<FlatList
style={{ marginTop: 15 }}
data={contacts && filter}
keyExtractor={(item) => `key-${item.id.toString()}`}
renderItem={renderItem}
refreshing={true}
initialNumToRender={10}
ListEmptyComponent={<Text message="No contacts found." />}
/>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
export default ContactList;

Related

When I call an API on My First Page I want to fire Second Page API at the same time how can I achieve it! | React Native

I am working on react native from 3 months means I am still a beginner ,Help me with this Functionality : What I want is that when I add a product to my shopping cart the cart number on my bottom tab should increase at the same time . How can I achieve it?
This is my add to cart screen Here I am adding my products to the cart
import {
View, Text, StyleSheet, ScrollView, TouchableOpacity, Alert, Image, ActivityIndicator, Dimensions
} from 'react-native'
import React, { useEffect, useState } from 'react'
import Ionicons from 'react-native-vector-icons/Ionicons'
import Octicons from 'react-native-vector-icons/Octicons'
import AsyncStorage from '#react-native-async-storage/async-storage'
import AntDesign from 'react-native-vector-icons/AntDesign';
import ImageZoom from 'react-native-image-pan-zoom';
import { UserProvider } from './UserContext'
const AddProduct = ({ route, navigation }) => {
const [count, setCount] = useState(1)
console.log("this is item quantity=>", count);
const prodId = route.params.prodId
console.log('data is coming from route', prodId);
const [prodImg, setProdImg] = useState("")
console.log("this is product image from use state=>", prodImg);
const [productName, setProductName] = useState("")
const [productDesc, setProductDesc] = useState("")
// const [in_stock, setIn_stock] = useState("")
const [availableQty, setAvailableQty] = useState("")
const [basePrice, setBasePrice] = useState("")
const [variations, setVariations] = useState([])
console.log("this is variation data", variations);
const [changePrice, setChangePrice] = useState("")
const [variationid, setVariationid] = useState("")
console.log('this is variation id=>', variationid);
const [selectedVar, setselectedVar] = useState(0)
const [customerId, setCustomerId] = useState("")
console.log("This is customer id ", customerId);
const baseUrl = "https://team.flymingotech.in/azamDeals/public/"
const [loader, setLoader] = useState(false)
const GetProductById = () => {
setLoader(true)
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch(`https://team.flymingotech.in/azamDeals/public/api/readByID/${route.params.prodId}/read`, requestOptions)
.then(response => response.json())
.then(result => {
console.log(result)
setProdImg(result[0].data.product_images)
setProductName(result[0].data.product_name)
setProductDesc(result[0].data.product_desc)
setAvailableQty(result[0].data.available_qty)
setBasePrice(result[0].data.base_price)
// setProductData(result.data)
setVariations(result[0].data?.variations)
// if (result && result.data) {
// setVariations(result.data.variations);
// } else {
// console.log('Could not retrieve data');
// }
setLoader(false)
})
.catch(error => {
console.log('error in getProductbyId api', error)
setLoader(false)
});
}
const getId = async () => {
try {
const customer_id = JSON.parse(await AsyncStorage.getItem("Customer_id"))
console.log("this is getting async storage data", customer_id);
setCustomerId(customer_id)
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getId()
GetProductById()
}, [route.params.prodId])
function increment() {
//setCount(prevCount => prevCount+=1);
setCount(function (prevCount) {
return (prevCount += 1);
});
}
function decrement() {
setCount(function (prevCount) {
if (prevCount > 0) {
return (prevCount -= 1);
} else {
return (prevCount = 0);
}
});
}
const AddCart = async () => {
if (variationid == 0) {
Alert.alert("Please select the product variation")
return false;
} else if (count == 0) {
Alert.alert("Qty cannot be 0")
}
else {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify({
"product_id": prodId,
"item_qty": count,
"item_price": changePrice,
"total_price": "",
"c_id": customerId,
"variation_id": variationid
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
await fetch("https://team.flymingotech.in/azamDeals/public/api/new_cart", requestOptions)
.then(response => response.json())
.then(result => {
console.log(result)
if (result.status == 1) {
Alert.alert('Added to cart')
}
})
.catch(error => console.log('error', error));
}
}
const onSelect = (id) => {
setselectedVar(id)
console.log(id);
}
const images = [
{
url:
'https://raw.githubusercontent.com/AboutReact/sampleresource/master/sample_img.png',
},
{
url:
'https://raw.githubusercontent.com/AboutReact/sampleresource/master/old_logo.png',
},
];
return (
<View style={styles.mainContainer}>
<View style={{ height: 80, backgroundColor: '#006C32', flexDirection: 'row', paddingTop: 25 }}>
<TouchableOpacity onPress={() => navigation.goBack()}>
<AntDesign style={{ paddingLeft: 20 }} name='arrowleft' size={30} color="white" />
</TouchableOpacity>
<Text style={{ paddingLeft: 20, fontSize: 20, color: 'white' }}>Product Detail</Text>
</View>
{/* <SearchHeader /> */}
{loader ?
<View style={{
alignItems: "center",
justifyContent: "center",
height: "90%"
}}>
<ActivityIndicator size={50} color="green" />
</View>
:
<ScrollView>
<View style={{ marginLeft: 15, marginRight: 15 }}>
<View>
{/* <Image style={{ height: 300, width: '100%', borderRadius: 10, marginTop: 10 }}
source={{ uri: prodImg }} /> */}
<ImageZoom
cropWidth={350}
cropHeight={300}
imageWidth={200}
imageHeight={200}>
<Image style={{ width: 200, height: 200 }}
source={{ uri: prodImg }} />
</ImageZoom>
<Text style={{ color: 'black', fontWeight: 'bold', marginTop: 10 }}>{productName}</Text>
<Text style={{ color: 'black', backgroundColor: 'white' }}>{productDesc}</Text>
<Text style={{ color: 'black', backgroundColor: 'white' }} >Stock:{availableQty}</Text>
<Text style={{ color: 'black', backgroundColor: 'white' }} >Base Price:₹{basePrice}</Text>
<Text style={{ color: 'black', backgroundColor: 'white' }} >Variation Price:₹{changePrice}</Text>
{/* <Text style={{ color: 'black', backgroundColor: 'white' }} >Variationid:{variationid}</Text> */}
<View style={{ marginTop: 14 }}>
<Text style={{ color: 'black', fontSize: 18, }}>Size</Text>
<View style={{
flexDirection: 'row',
justifyContent: 'space-around', height: 25
}}>
{/* {console.log("type", productData.variations.length)} */}
<View >
{variations?.length > 0 && variations.map((item, i) => (
<View key={i}>
<TouchableOpacity onPress={() => setChangePrice(item.variation_price,) | setVariationid(item.id) |onSelect(item.id)} style={{
height: 70, width: 120,
borderWidth: 0.5, borderColor: 'grey', borderRadius: 10,
justifyContent: 'center', alignItems: 'center',
backgroundColor: selectedVar === item.id ? "lightgrey" : "#fff"
}}>
<Text style={{ color: 'black', }}>{item.variation_label}</Text>
<Text style={{ color: 'black', }}>{item.variation_weight}</Text>
</TouchableOpacity>
</View>
))}
</View>
{/* <FlatList horizontal
data={productData}
renderItem={(item)=>renderItem(item)}
/> */}
{/* <Pressable onPress={() => getSize('s')} style={[styles.variable, { backgroundColor: size === 's' ? '#D1D1D1' : '#FFF' }]}><Text style={styles.variableValue}>S</Text></Pressable>
<Pressable onPress={() => getSize('m')} style={[styles.variable, { backgroundColor: size === 'm' ? '#D1D1D1' : '#FFF' }]}><Text style={styles.variableValue}>M</Text></Pressable>
<Pressable onPress={() => getSize('l')} style={[styles.variable, { backgroundColor: size === 'l' ? '#D1D1D1' : '#FFF' }]}><Text style={styles.variableValue}>L</Text></Pressable> */}
</View>
</View>
<View style={{ flexDirection: "row", marginTop: 50, justifyContent: 'space-between', paddingBottom: 10 }}>
<View style={styles.countButton}>
<TouchableOpacity onPress={decrement} style={{ alignSelf: 'center', marginLeft: 5 }}>
<Octicons name="dash" size={28} color="black" />
</TouchableOpacity>
<Text style={{ alignSelf: 'center', fontSize: 17, marginLeft: 4, color: 'black' }}>{count}</Text>
<TouchableOpacity onPress={increment} style={{ alignSelf: 'center' }}>
<Ionicons name="add" size={28} color="black" />
</TouchableOpacity>
</View>
<TouchableOpacity onPress={AddCart} style={{
backgroundColor: '#006C32', height: 40
, justifyContent: 'center', alignItems: 'center', width: 150, borderRadius: 5,
}}>
<Text style={{ color: 'white', fontWeight: 'bold' }}>Add to Cart</Text>
</TouchableOpacity>
</View>
{/* <View>
<TouchableOpacity style={{
width: 300, marginTop: 20, backgroundColor: 'darkgreen', height: 50
, borderRadius: 10, justifyContent: 'center', alignItems: 'center', alignSelf: 'center'
}}>
<Text style={{ color: 'white', fontWeight: 'bold' }}>Buy Now</Text>
</TouchableOpacity>
</View> */}
</View>
</View>
</ScrollView>
}
</View>
)
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
backgroundColor: 'white'
},
image: {
height: 300, width: '100%',
},
countButton: {
backgroundColor: 'white', height: 40, borderWidth: 0.5, borderColor: 'grey'
, width: 100, flexDirection: 'row', borderRadius: 10, justifyContent: 'space-between',
},
variable: {
padding: 5,
color: 'black',
borderWidth: 1,
borderColor: '#999999',
borderRadius: 4,
},
variableValue: {
fontWeight: '700',
},
})
export default AddProduct
And this is my screen where I am showing the count of the products as a badge using an API it is working it is showing the data but when I refresh the app that time only it shows the count
import { View, Text, StyleSheet } from 'react-native'
import React, { useEffect, useState } from 'react'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { getFocusedRouteNameFromRoute } from '#react-navigation/native';
import Ionicons from 'react-native-vector-icons/Ionicons'
import User from 'react-native-vector-icons/FontAwesome'
// screens
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import Home from '../screens/HomeScreen/Home';
import { CustomerStack, Cart, Profile } from './CustomerStack';
import { Badge } from 'react-native-elements';
import AsyncStorage from '#react-native-async-storage/async-storage';
// Screen Names
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const BottomTabNav = ({ route, navigation }) => {
const [Count, setCount] = useState("")
console.log("this is Count of cart=>",Count);
useEffect(() => {
getCartCount()
}, [])
const getCartCount = async () => {
const customer_id = JSON.parse(await AsyncStorage.getItem("Customer_id"))
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch(`https://team.flymingotech.in/azamDeals/public/api/countCartItems/${customer_id}`, requestOptions)
.then(response => response.json())
.then(result => {
console.log(result)
setCount(result.data)
})
.catch(error => console.log('error', error));
}
<Tab.Screen
name="CustomerStack"
component={CustomerStack}
options={({ route }) => ({ tabBarStyle: getTabBarStyle(route) })} />
const getTabBarStyle = (route) => {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'CustomerStack';
let display = (routeName === 'Player') ? 'none' : 'flex';
return { display }
}
return (
<Tab.Navigator initialRouteName='CustomerStack'
tabBarOptions={{
// activeTintColor: 'red',
inactiveTintColor: 'white',
}}
screenOptions={({ route, }) => ({
tabBarStyle: {
backgroundColor: '#006C32',
},
tabBarIcon: ({ focused, color, size }) => {
let iconName;
let rn = route.name;
if (rn === "CustomDrawer") {
iconName = focused ? 'home' : 'home'
}
else if (rn === "CustomerStack") {
iconName = focused ? 'home' : 'home'
}
else if (rn === "Cart") {
<View style={styles.unreadBadge}>
<Text style={styles.unreadBadgeText}>11</Text>
</View>
iconName = focused ? 'shopping-cart' : 'shopping-cart'
} else if (rn === "Account") {
iconName = focused ? 'user' : 'user'
}
return <User name={iconName} size={size} color={color} />
},
})}>
<Tab.Screen options={{ headerShown: false, tabBarActiveTintColor: 'white', }} name="CustomerStack" component={CustomerStack} />
<Tab.Screen options={{
headerShown: false, tabBarActiveTintColor: 'white',
tabBarBadge: Count
}} name="Cart" component={Cart} />
<Tab.Screen options={{ headerShown: false, tabBarActiveTintColor: 'white', }} name="Account" component={Profile} />
</Tab.Navigator>
)
}
const styles = StyleSheet.create({
unreadBadge: {
backgroundColor: '#FF3250',
position: 'absolute',
left: 20,
bottom: 18,
width: 25,
height: 18,
borderradius: 25,
alignItems: 'center',
justifyContent: 'center',
zIndex: 100, // this one is used to put message notify on top of icon
},
unreadBadgeText: {
color: 'white',
fontWeight: '600',
},
})
export default BottomTabNav
What I was going to try is that keep calling that API every 5 seconds then after calling the API So many times it will give Too many request error .
Whether I should use UseContext or Pass data through both the screen and call API I don't get it!

react native modal takes 2 second to open

In my app you can join a group. There are storys and messages. If there is no story or messages modal is open fast. But If I have 30 text messages to render and want to click to open my modal then it takes 1-2 seconds or later to open. The same issue if I click a button. The opacity and function works until 1-2 seconds but if there is no much messages to render then it goes fast. I need help.
message render function
<FlatList
data={globalMessages}
style={{width: '100%'}}
contentContainerStyle={{marginLeft: 12}}
renderItem={({ item }) => (
<TouchableOpacity onLongPress={() => deleteMessage(item.id)} style={{width: 230, flexDirection: 'column', backgroundColor: '#eee', padding: 8, borderRadius: 12, margin: 12, marginLeft: 0, marginTop: 0}}>
<Text style={{fontFamily: 'poppins-light', fontSize: 16, color: '#333'}}>{item.message}</Text>
<Text style={{fontFamily: 'poppins-medium', fontSize: 12, color: '#333'}}>{item.date}</Text>
</TouchableOpacity>
)}
keyExtractor={item => item.id.toString()}
// ListHeaderComponent={() => this.renderHeader()}
horizontal={false}
nestedScrollEnabled
showsHorizontalScrollIndicator={false}
// Performance settings
removeClippedSubviews={true} // Unmount components when outside of window
initialNumToRender={2} // Reduce initial render amount
maxToRenderPerBatch={1} // Reduce number in each render batch
updateCellsBatchingPeriod={100} // Increase time between renders
windowSize={4} // Reduce the window size
/>
fullCode:
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect, useRef } from 'react';
import { StyleSheet, Text, TextInput, View, TouchableOpacity, Image, Dimensions, ImageBackground, ActivityIndicator, ScrollView, FlatList, TouchableWithoutFeedback } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import { AntDesign, Ionicons } from '#expo/vector-icons';
import Modal from 'react-native-modal';
import * as ImagePicker from 'expo-image-picker';
import uploadStoryAPI from '../api/uploadStory';
import createMessageAPI from '../api/createMessage';
import io from 'socket.io-client/dist/socket.io';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const Room = ({ route }) => {
const socket = io('http://192.168.0.249:3000', {
transports: ['websocket']
});
const [connected, setConnected] = useState(false);
const [areaHeight, setAreaHeight] = useState(0);
const [chatMessage, setChatMessage] = useState('');
const [globalMessages, setGlobalMessages] = useState(route.params.messages || []);
const [loadSendChatMessage, setLoadSendChatMessage] = useState(false);
const [alignItem, setAlignItem] = useState('center');
const [addStory, setAddStory] = useState(false);
const [storys, setStorys] = useState(route.params.storys || []);
const [modalImagePreview, setModalImagePreview] = useState(false);
const [modalDeleteMessage, setModalDeleteMessage] = useState(false);
const [imagePreview, setImagePreview] = useState('');
const [loadUpload, setLoadUpload] = useState(false);
const [sourceStory, setSourceStory] = useState({
uri: null,
type: null,
name: null
});
useEffect(() => {
socket.on('connect', () => {
setConnected(true);
console.log('user connected');
});
socket.on('getmessage', message => {
globalMessages.length > 0 ?
setGlobalMessages(prevState => {
return [...prevState, message]
}) : setGlobalMessages([message]);
handleAddMessage();
});
});
const handleAlign = () => {
areaHeight > 100 ? setAlignItem('flex-end') : setAlignItem('center');
}
const handleAddStory = async () => {
try {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [1, 1]
});
setAddStory(false);
if(result.cancelled) {
setAddStory(false);
return;
}
let localUri = result.uri;
let filename = localUri.split('/').pop();
// Infer the type of the image
let match = /\.(\w+)$/.exec(filename);
let type = match ? `image/${match[1]}` : `image`;
setImagePreview(localUri);
setSourceStory({
uri: localUri,
type,
filename
});
setModalImagePreview(true);
} catch(e) {
return;
}
};
const handleUploadToServer = async () => {
try {
setLoadUpload(true);
let res = await uploadStoryAPI(route.params.roomID, sourceStory);
res.upload && storys.length > 0
? setStorys(prevState => {
return [{
source: res.source
}, ...prevState]
}) : setStorys([{ source: res.source}]);
console.log(`D ${storys}`)
res.upload ? (setLoadUpload(false),setModalImagePreview(false)) : setLoadUpload(false);
} catch(e) {
return e;
}
};
const handleAddMessage = async () => {
try {
setLoadSendChatMessage(true);
const res = await createMessageAPI(route.params.roomID, chatMessage);
console.log(res);
//scrollViewRef.current.scrollToEnd({animated: true});
setLoadSendChatMessage(false);
} catch(e) {
console.log(e);
return e;
}
};
const deleteMessage = async id => {
try {
console.log(id);
} catch(e) {
return e;
}
};
return (
<KeyboardAwareScrollView keyboardShouldPersistTaps="handled" style={{margin: 0, padding: 0}}>
<View style={{height: height - 155, backgroundColor: '#fff'}}>
<View>
<ScrollView>
<Text style={styles.title}>Storys</Text>
{
storys.length > 0
?
<FlatList
data={storys}
contentContainerStyle={{marginLeft: 8}}
renderItem={({ item }) => (
<TouchableOpacity key={`index-${item.source}`} style={{padding: 0, marginRight: 16, borderWidth: 2, justifyContent: 'center', alignItems: 'center', borderRadius: 100, borderColor: '#1ab7ff', height: 68, width: 68}}>
<Image resizeMode="contain" source={{uri: `http://192.168.0.249:3000/build/${item.source}`}} style={{height: 55, width: 55, borderRadius: 500}} />
</TouchableOpacity>
)}
keyExtractor={item => item.source.toString()}
// ListHeaderComponent={() => this.renderHeader()}
nestedScrollEnabled
horizontal
showsHorizontalScrollIndicator={false}
// Performance settings
removeClippedSubviews={true} // Unmount components when outside of window
initialNumToRender={2} // Reduce initial render amount
maxToRenderPerBatch={1} // Reduce number in each render batch
updateCellsBatchingPeriod={100} // Increase time between renders
windowSize={7} // Reduce the window size
/>
:
<Text>Es sind zurzeit keine Storys vorhanden.</Text>
}
<Text style={styles.title}>Nachrichten</Text>
{
globalMessages.length > 0
?
<FlatList
data={globalMessages}
style={{width: '100%'}}
contentContainerStyle={{marginLeft: 12}}
renderItem={({ item }) => (
<TouchableOpacity onLongPress={() => deleteMessage(item.id)} style={{width: 230, flexDirection: 'column', backgroundColor: '#eee', padding: 8, borderRadius: 12, margin: 12, marginLeft: 0, marginTop: 0}}>
<Text style={{fontFamily: 'poppins-light', fontSize: 16, color: '#333'}}>{item.message}</Text>
<Text style={{fontFamily: 'poppins-medium', fontSize: 12, color: '#333'}}>{item.date}</Text>
</TouchableOpacity>
)}
keyExtractor={item => item.id.toString()}
// ListHeaderComponent={() => this.renderHeader()}
horizontal={false}
nestedScrollEnabled
showsHorizontalScrollIndicator={false}
// Performance settings
removeClippedSubviews={true} // Unmount components when outside of window
initialNumToRender={2} // Reduce initial render amount
maxToRenderPerBatch={1} // Reduce number in each render batch
updateCellsBatchingPeriod={100} // Increase time between renders
windowSize={4} // Reduce the window size
/>
: null
}
</ScrollView>
</View>
</View>
<View style={{flex: 1, paddingLeft: 16, paddingTop: 8, paddingRight: 16, paddingBottom: 12, backgroundColor: '#fff', alignItems: alignItem, justifyContent:'space-between', flexDirection: 'row'}}>
<TouchableOpacity onPress={() => setAddStory(true)}>
<AntDesign name="pluscircleo" size={32} color="#444" />
</TouchableOpacity>
<TextInput
onChangeText={e => setChatMessage(e)}
// onFocus={() => setAlignItem('flex-end')}
onEndEditing={() => handleAlign()}
value={chatMessage}
multiline={true}
style={[styles.input, {height: Math.max(50, areaHeight)}]}
onContentSizeChange={e => {
setAreaHeight(e.nativeEvent.contentSize.height);
}}
placeholder="Gebe eine Nachricht ein..." />
<TouchableOpacity onPress={() => chatMessage.length > 0 ? socket.emit('getmessage', {
chatMessage,
date: Date.now()
}) : null} style={{padding: 8, paddingRight: 10, borderRadius: 8, backgroundColor: '#1ab7ff'}}>
{ !loadSendChatMessage ? <Ionicons name="paper-plane-outline" size={28} color="#fff" /> : <ActivityIndicator style={{height: 20, width: 20}} color="#fff" />}
</TouchableOpacity>
</View>
{ /* Ask user if he wants to upload */}
<Modal
isVisible={modalImagePreview}
swipeDirection="down"
onSwipeComplete={() => setModalImagePreview(false)}
onBackButtonPress={() => setModalImagePreview(false)}
onBackdropPress={() => setModalImagePreview(false)}
backdropTransitionOutTiming={0}
// style={{margin: 0, padding: 0}}
>
<View style={{ backgroundColor: '#fff', borderRadius: 12, padding: 12}}>
<Text style={{fontFamily: 'poppins-light', color: '#333', fontSize: 18, textAlign: 'center', marginBottom: 10}}>Möchtest du diese Story hochladen?</Text>
{ <Image resizeMode="contain" style={{height: 250, borderRadius: 12}} source={{uri: imagePreview}} /> }
<View style={{flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', marginTop: 20, marginBottom: 10}}>
<TouchableOpacity onPress={() => setModalImagePreview(false)}>
<Text style={{fontFamily: 'poppins-light', color: '#333', borderWidth: 1, borderColor: '#eee', padding: 10, paddingTop: 13, borderRadius: 8}}>Abbrechen</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => handleUploadToServer()} style={{backgroundColor: '#1ab7ff', padding: 10, paddingTop: 13, borderRadius: 8}}>
{ !loadUpload ? <Text style={{fontFamily: 'poppins-light', color: '#fff'}}>Story hinzufügen</Text> : <ActivityIndicator style={{height: 20, width: 20}} color="#fff" /> }
</TouchableOpacity>
</View>
</View>
</Modal>
{ /* Modal open Story */ }
<Modal
isVisible={addStory}
swipeDirection="down"
onSwipeComplete={() => setAddStory(false)}
onBackButtonPress={() => setAddStory(false)}
onBackdropPress={() => setAddStory(false)}
backdropTransitionOutTiming={0}
style={{margin: 0, padding: 0}}
>
<View style={{position: 'absolute', bottom: 0, backgroundColor: '#fff', width: '100%', justifyContent: 'center', alignItems: 'center', borderTopLeftRadius: 20, borderTopRightRadius: 20}}>
<TouchableOpacity onPress={() => handleAddStory()} style={{padding: 20, backgroundColor: '#1ab7ff', width: width, justifyContent: 'center', alignItems: 'center',borderTopLeftRadius: 20, borderTopRightRadius: 20}}>
<Text style={{color: '#fff', fontFamily: 'poppins-light'}}>Story hinzufügen</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => setAddStory(false)} style={{padding: 20}}>
<Text>Abbrechen</Text>
</TouchableOpacity>
</View>
</Modal>
</KeyboardAwareScrollView>
)
};

Card drop-down on react native

Is it possible to achieve a component drop on react native?
Something like this. Sorry for the paint skills. Thank you in advance .
You can create a custom component like below, You can change the render label to support the view you want.
This sample needs the data to be like the below object but you can create your own object.
const dataArray = [{value: 'Car', id: 1,},{value: 'Van',id: 2},{ value: 'Bus',id: 3}];
//Usage
<CustomDropDown data={dataArray} />
const CustomDropDown = (props) => {
const [open, setOpen] = React.useState(false);
const [selected, setSelected] = React.useState(-1);
const renderLabel = (item) => {
return (
<View
style={{
width: 200,
height: 60,
borderWidth: 1,
borderRadius: 10,
padding: 5,
marginVertical: 3,
}}>
<Text style={{ fontSize: 20 }}>{item.value}</Text>
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Text>{item.value}</Text>
<Text style={{ fontSize: 15 }}>{item.value}</Text>
</View>
</View>
);
};
const renderItem = (item) => {
return (
<TouchableOpacity
onPress={() => {
setSelected(item.id);
setOpen(!open);
//Call back to external state
}}>
{renderLabel(item)}
</TouchableOpacity>
);
};
return (
<View>
<TouchableOpacity style={{}} onPress={() => setOpen(!open)}>
{selected === -1 && <Text>Place holder text</Text>}
{selected !== -1 &&
renderLabel(props.data.find((x) => x.id === selected))}
</TouchableOpacity>
{open && (
<View
style={{
position: 'absolute',
top: 70,
}}>
{props.data.map((item) => renderItem(item))}
</View>
)}
</View>
);
};

Webview Uri Redirect by scanning barcodes with React Native, Expo

I am creating a barcode scanner using React Native and Expo.
I am trying to pass a new URL to a WebView after scanning a barcode.
But I am not sure how.
Please help.
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setModalVisible(true);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column'
}}>
<Modal
animationType="slide"
transparent={false}
visible={modalVisible}
onRequestClose={() => {
setScanned(false);
}}>
<View style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
source={{ uri: 'http://domain.biz/' }}
/>
<TouchableHighlight
style={{
backgroundColor:'black',
padding: 15,
alignItems: 'center'
}}
onPress={() => {
setModalVisible(!modalVisible);
setScanned(false);
}}
underlayColor='slategray'
>
<Text style={{ color:'white', fontSize: 15 }}>Re Scan</Text>
</TouchableHighlight>
</View>
</Modal>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{ marginBottom: 100 }}>
<View style={{ alignItems: 'center', marginBottom: 5 }}>
<Image
style={{
width: 100,
height: 100,
resizeMode: 'contain',
marginBottom: 20,
}}
source={{ uri: 'http://domain.biz/img/logo_dark.png' }}
/>
<Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold', paddingBottom: 10}}>
QR Code Reader v0.5
</Text>
</View>
<View
style={{
borderColor: 'white',
borderTopWidth: 5,
borderBottomWidth: 5,
borderLeftWidth: 1,
borderRightWidth: 1,
paddingVertical: 80,
paddingHorizontal: 100,
}}
/>
<View style={{ alignItems: 'center', marginTop: 5 }}>
<Text style={{ color: 'white', fontSize: 15}}>
QR Scan...
</Text>
</View>
</View>
</BarCodeScanner>
</View>
);
}
I am creating a barcode scanner using React Native and Expo.
I am trying to pass a new URL to a WebView after scanning a barcode.
But I am not sure how.
Please help.
This should do the work. I save the url from the scanner in state.uri and use that instead of a static string.
For testing purposes I used this barcode which leads to this answer:
Best, Paul
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button, Modal, TouchableHighlight, Image } from 'react-native';
import { WebView } from 'react-native-webview';
import { BarCodeScanner } from 'expo-barcode-scanner';
export default function App(){
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(true);
const [modalVisible, setModalVisible] = useState(true);
const [uri, setUri] = useState('https://stackoverflow.com/questions/61977154/webview-uri-redirect-by-scanning-barcodes-with-react-native-expo');
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setModalVisible(true);
// console.warn("Scan returned " + data);
setUri({ uri: data })
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column'
}}>
<Modal
animationType="slide"
transparent={false}
visible={modalVisible}
onRequestClose={() => {
setScanned(false);
}}>
<View style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
source={{uri: uri['uri']}}
/>
<TouchableHighlight
style={{
backgroundColor:'black',
padding: 15,
alignItems: 'center'
}}
onPress={() => {
setModalVisible(!modalVisible);
setScanned(false);
}}
underlayColor='slategray'
>
<Text style={{ color:'white', fontSize: 15 }}>Re Scan</Text>
</TouchableHighlight>
</View>
</Modal>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{ marginBottom: 100 }}>
<View style={{ alignItems: 'center', marginBottom: 5 }}>
<Image
style={{
width: 100,
height: 100,
resizeMode: 'contain',
marginBottom: 20,
}}
source={{ uri: 'http://domain.biz/img/logo_dark.png' }}
/>
<Text style={{ color: 'white', fontSize: 20, fontWeight: 'bold', paddingBottom: 10}}>
QR Code Reader v0.5
</Text>
</View>
<View
style={{
borderColor: 'white',
borderTopWidth: 5,
borderBottomWidth: 5,
borderLeftWidth: 1,
borderRightWidth: 1,
paddingVertical: 80,
paddingHorizontal: 100,
}}
/>
<View style={{ alignItems: 'center', marginTop: 5 }}>
<Text style={{ color: 'white', fontSize: 15}}>
QR Scan...
</Text>
</View>
</View>
</BarCodeScanner>
</View>
);
}
Here it is, but I have passed the data from the other page name:index.js.
You can use the linking component to open every URL passed through {data}
import React from "react";
import { View, Text, Linking, TouchableOpacity } from "react-native";
const detail = ({ route, navigation }) => {
const data = route.params;
const [uri, setUri] = React.useState({});
return (
<View>
<TouchableOpacity onPress={() => Linking.openURL(data)}>
<Text>{data}</Text>
</TouchableOpacity>
</View>
);
};
export default detail;

How to create dynamic checkbox in react native

I am able to create the dynamic checkbox but i need to check and uncheck it separately, right now if i check one everything gets checked and if i uncheck everything gets unchecked.
How to change the value of checkbox separately for each checkbox from state?
import React from 'react';
import {View,Text,StyleSheet,TouchableOpacity,Image,Switch,Platform,Dimensions,PixelRatio,} from'react-native';
import ImagePicker from 'react-native-image-picker';
import { Input, Button } from 'react-native-elements';
import { moderateScale } from 'react-native-size-matters';
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const calcHeight = x => PixelRatio.roundToNearestPixel((deviceHeight * x) / 100);
const calcWidth = x => PixelRatio.roundToNearestPixel((deviceWidth * x) / 100);
class ErrorScreen extends React.Component {
constructor() {
super();
this.state = {
arr: [],
parkPay: false,
itemChecked: false,
index: null,
};
}
functionTwo = () => {
alert('func 2');
this.setState(() => ({
parkPay: true,
}));
};
checkedItem = index => {
console.log('this is index', index);
// let itemChecked = this.state.itemChecked
if (this.state.index != index) {
this.setState(() => ({
index: index,
itemChecked: !this.state.itemChecked,
}));
}
};
addParkField = () => {
console.log('jjjjj');
console.log(' ^^ props in parking form ^^ ', this.props);
let x = 0;
this.setState(() => ({
arr: [...this.state.arr, ''],
}));
// this.addFieldSecond()
// this.props.addParkFieldSecond()
};
render() {
return (
<View>
<View
style={{flex: 1, paddingRight: calcWidth(4),paddingLeft: calcWidth(6), paddingTop: calcHeight(4),paddingBottom: calcHeight(4),
}}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View
style={{ paddingLeft: calcWidth(2), paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios' ? styles.switchIOS : styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value); this.functionTwo()}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>Paid By Customer</Text>
</View>
</View>
<View style={{}}>
{this.state.arr.map((extra, index) => {
return (
<View
style={{
flex: 1,
paddingRight: calcWidth(4),
paddingLeft: calcWidth(20),
paddingTop: calcHeight(15),
paddingBottom: calcHeight(4),
}}
key={index}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.handleAmount}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View style={{ paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios'
? styles.switchIOS
: styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value);}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>
Paid By Customer
</Text>
</View>
</View>
);
})}
<View>
<View
style={{ paddingLeft: calcWidth(60), paddingTop: calcHeight(2) }}>
<TouchableOpacity
style={[styles.cardCirclePassenger]}
onPress={this.addParkField}>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
paddingTop: calcHeight(2.2),
}}>
{/* <Image
style={{width: 24, height: 24}}
source={require('../../images/Group424.png')}
/> */}
<Text>Add</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
cardCirclePassenger: {
backgroundColor: '#31588A',
marginBottom: 10,
marginLeft: '5%',
width: 60,
height: 60,
borderRadius: 60 / 2,
borderColor: 'white',
shadowOpacity: 0.2,
shadowRadius: 1,
shadowOffset: {
width: 3,
height: 3,
},
borderWidth: 1,
},
switchIOS: {
transform: [
{ scaleX: moderateScale(0.7, 0.2) },
{ scaleY: moderateScale(0.7, 0.2) },
],
},
switchAND: {
transform: [
{ scaleX: moderateScale(1, 0.2) },
{ scaleY: moderateScale(1, 0.2) },
],
},
});
export default ErrorScreen;
i worked around a little bit and found the below way to generate dynamic checboxes along with separate state values. hope this helps someone.
The below code creates dynamic key-value pairs in state. if you console.log the state in your render you'll see (check0:true check1:true check2: false ....) .
<Switch
value={this.state[`check${key}`]}
onValueChange={value => this.setState({ [`check${key}`]: value })}
/>