Webview Uri Redirect by scanning barcodes with React Native, Expo - react-native

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;

Related

FlatList react native not scrolling

I have made sure that the parent Views contain flex:1, and I have wrapped the FlatList in a view with Flex 1 but nothing I seem to try enables my flat list to scroll.
I have gone through previous posts and none of the solutions have worked
Any help or suggestions would be greatly appreciated.
This is my code in order from parent to children
const App = () => {
return (
<View style={styles.container}>
<AuthProvider>
<Home />
</AuthProvider>
</View>
);
};
const styles = StyleSheet.create({
container: {flex: 1},
});
export default App;
const Home = () => {
const [userAuth] = useContext(AuthContext);
//{userAuth.auth && <Header title={'Stokebook'} />}
return (
<View style={styles.container}>
{userAuth.auth && <Profile />}
{!userAuth.auth && <LoginHome />}
</View>
);
};
const styles = StyleSheet.create({
container: {flex: 1},
});
const Profile = () => {
const [userAuth] = useContext(AuthContext);
const [Posts, setPosts] = useState();
const [isLoading, setisLoading] = useState(true);
//Loading screen will live here
useEffect(() => {
axios({
method: 'get',
url: 'http://192.168.1.112:3000/posts',
headers: {
Authorization: `${userAuth.token}`,
},
})
.then(response => {
setPosts(response.data.flat());
})
.then(setisLoading(false))
.catch(err => setPosts(err));
}, []);
return (
<View style={styles.PostContainer}>
<FlatList
contentContainerStyle={{height: '100%'}}
data={Posts}
renderItem={({item}) => <Post post={item} />}
/>
</View>
);
};
const styles = StyleSheet.create({
PostContainer: {
backgroundColor: 'grey',
flex: 1,
},
});
const Post = ({post}) => {
return (
<View style={styles.PostContainer}>
<View style={styles.PostHeader}>
<View style={styles.ProfileInfoView}>
<Text>Michael Wong</Text>
<Text>Yesterday at 6.30pm at point leo</Text>
</View>
</View>
<View style={styles.WaveInfo}>
<View>
<Text>Wave height </Text>
<Text> 6ft</Text>
</View>
<View>
<Text>tide </Text>
<Text>low</Text>
</View>
<View>
<Text>Break</Text>
<Text>crunchies</Text>
</View>
<View>
<Text>Wind </Text>
<Text>NE 10km/hr</Text>
</View>
</View>
<View style={styles.ImageView}>
<Image
source={require('../wave.webp')}
style={{flex: 1, width: undefined, height: undefined}}
/>
</View>
<View style={styles.FeedbackView}>
<Text>
<Icon name="thumbs-up" size={15} color="black" /> 13
</Text>
<Text>3 comments</Text>
</View>
<View style={styles.FooterView}>
<View style={styles.IconView}>
<Icon name="thumbs-up" size={30} color="white" />
<Icon name="envelope" size={30} color="white" />
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
PostContainer: {
backgroundColor: 'beige',
height: '80%',
},
PostHeader: {
height: '20%',
padding: '4%',
flexDirection: 'row',
},
Profileimg: {
height: 30,
width: 30,
borderRadius: 30,
},
ProfileInfoView: {
paddingLeft: '5%',
justifyContent: 'space-around',
},
WaveInfo: {
borderTopWidth: 1,
height: '12%',
flexDirection: 'row',
justifyContent: 'space-evenly',
alignItems: 'center',
},
ImageView: {
height: '60%',
width: '100%',
},
FeedbackView: {
height: '10%',
backgroundColor: 'beige',
flexDirection: 'row',
justifyContent: 'space-between',
padding: '3%',
alignItems: 'center',
},
FooterView: {
width: '100%',
height: '15%',
flexDirection: 'row',
justifyContent: 'center',
backgroundColor: 'black',
borderBottomColor: 'grey',
borderBottomWidth: 12,
},
IconView: {
height: '100%',
width: '70%',
justifyContent: 'space-around',
alignItems: 'center',
flexDirection: 'row',
},
});
export default Post;

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>
)
};

How to scroll To next item on a button click using FlatList in React Native?

I have an array of months which I am using to display months using a horizontal FlatList. I want the months to change using 2 buttons that are forward button to change the month in increasing order i.e from January to February and so on and a back button to change the month backwards i.e from January to December.
How can I make the buttons do so. Below monthName is an array that contains all the month names.
<ScrollView style={{flexGrow: 1}}>
<View style={{flex: 1, backgroundColor: '#fff', height: hp('130')}}>
<View
style={{
justifyContent: 'space-evenly',
width: wp('48'),
}}>
<FlatList
data={monthName}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={(month, index) => (
<View>
<Months
showMonth={month.item}
id={month.id}
refer={flatRef}
/>
</View>
)}
keyExtractor={(item, index) => item.id.toString()}
horizontal
// snapToInterval={Dimensions.get('window').width}
snapToAlignment={'center'}
ref={(node) => (flatRef = node)}
/>
</View>
<View
style={{
justifyContent: 'space-evenly',
width: wp('12'),
}}>
{/* {} */}
<IonIcons.Button --> the button that makes the month increment.
name="arrow-forward"
size={25}
backgroundColor="white"
color="black"
// onPress={() => console.log('pressed')}
onPress={() => {
flatRef.scrollToIndex({index: ?});
}}
/>
</View>
</View>
</ScrollView>
try to access ref using current and it should work
this.flatRef.current.scrollToIndex({index: monthName.length > this.state.currentindex ? this.state.currentindex++ : this.state.currentindex });
import React, { useRef } from 'react';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { wp } from '../../constants/scaling';
import { colors } from '../../constants/theme';
import bookingprocess from '../../data/BookingProcess';
import { textStyles } from '../../styles/textStyles';
import { RFValue } from 'react-native-responsive-fontsize';
import AntDesign from 'react-native-vector-icons/AntDesign';
const BookingProcess = ({}) => {
const flatListRef = useRef(FlatList);
const nextPress = index => {
if (index <= 2) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index + 1
});
}
};
const backPress = index => {
if (index >= 1) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index - 1
});
}
};
return (
<View
style={{
...styles.cardView,
padding: 0,
elevation: 0,
borderWidth: 1,
borderColor: '#f2f2f2',
overflow: 'hidden'
}}>
<View
style={{
padding: wp(2),
backgroundColor: colors.primaryColor
}}>
<Text
style={{
...textStyles.heading,
color: '#fff'
}}>
Booking Process
</Text>
</View>
<Text
style={{
...textStyles.mediumheading,
padding: wp(2),
paddingBottom: 0
}}>
You can reserve your parking slot in advance. Please follow
these four simple steps to book your parking slot.
</Text>
<FlatList
data={bookingprocess}
horizontal={true}
ref={flatListRef}
contentContainerStyle={{ padding: wp(2) }}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => item.id}
renderItem={({ item, index }) => {
return (
<View style={styles.innerCard}>
{item.image}
<View style={styles.ButtonBox}>
<TouchableOpacity
onPress={() => backPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="leftcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => nextPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="rightcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
</View>
<View style={styles.innercardHeaderView}>
<Text style={styles.headingTextNumber}>
{item.id}. {item.title}
</Text>
</View>
<Text style={styles.description}>
{item.description}
</Text>
</View>
);
}}
/>
</View>
);
};
export default BookingProcess;
const styles = StyleSheet.create({
cardView: {
backgroundColor: colors.white,
margin: wp(2),
elevation: 4,
borderRadius: wp(2),
padding: wp(2),
width: wp(94)
},
innerCard: {
margin: wp(2),
borderRadius: wp(2),
padding: wp(0),
paddingTop: 0,
paddingHorizontal: 0,
overflow: 'hidden',
width: wp(90),
elevation: 5,
marginLeft: 0,
padding: wp(2),
backgroundColor: '#fff'
},
ButtonBox: {
position: 'absolute',
flexDirection: 'row',
right: 0,
justifyContent: 'space-between',
width: wp(20),
padding: wp(2)
},
innercardHeaderView: {
backgroundColor: '#0000',
flexDirection: 'row',
padding: wp(2),
paddingBottom: 0,
alignItems: 'center'
},
headingTextNumber: {
...textStyles.heading,
color: colors.primaryColor,
textAlign: 'center',
alignSelf: 'center',
textAlignVertical: 'center'
},
description: {
...textStyles.mediumheading,
paddingHorizontal: wp(2),
textAlign: 'justify'
}
});
Instead of using a FlatList I would suggest you to make a state variable and execute it like this
Working example - Here
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { AntDesign } from '#expo/vector-icons';
...
const [SelectMonth, SetSelectMonth] = React.useState(monthName[0]);
const NextPress = () => {
if (SelectMonth.id !== 12) {
let temp = monthName.find((c) => c.id === SelectMonth.id + 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
const PrevPress = () => {
if (SelectMonth.id !== 1) {
let temp = monthName.find((c) => c.id === SelectMonth.id - 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
return (
<View style={styles.container}>
<View style={styles.CalenderBox}>
<AntDesign
name="caretleft"
size={30}
color="black"
onPress={() => PrevPress()}
/>
<View style={styles.MonthNameBox}>
<Text style={{ fontWeight: 'bold', fontSize: 24 }}>
{SelectMonth.name}
</Text>
</View>
<AntDesign
name="caretright"
size={30}
color="black"
onPress={() => NextPress()}
/>
</View>
</View>
);

calling modal from another component in react native wont open modal

I am trying to open a modal from another component.
this is in my parent component:
const [modalVisible, setModalVisible] = useState(false);
<TouchableOpacity
style={styles.gateBtn}
onPress={() => {
setModalVisible(true);
}}
>
<Text style={styles.gateBtnText}>Show Modal</Text>
<OpenModal isModalVisible={modalVisible} />
</TouchableOpacity>
and this is my OpenModal.js
import React, { useState } from "react";
import {
StyleSheet,
View,
Text,
Alert,
Modal,
TouchableHighlight,
} from "react-native";
function OpenModal(props) {
const [modalVisible, setModalVisible] = useState(false);
return (
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
setModalVisible(!modalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2,
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center",
},
modalText: {
marginBottom: 15,
textAlign: "center",
},
});
export default OpenModal;
however It seems like I am doing something wrong,
I am trying to pass modalVisible to OpenModal by using isModalVisible={modalVisible} and modalVisible is already defined as false, when clicking on the button it becomes true, but in my OpenModal component It seems like its undefined, and it doesnt open the modal at all. What am I missing here?
you need to pass in the setModalVision, then use the props.modalVisible from the parent component.
in parent
<OpenModal isModalVisible={modalVisible} setModalVisible={setModalVisible} />
child component
function OpenModal(props) {
return (
<Modal
animationType="slide"
transparent={true}
visible={props.isModalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
props.setModalVisible(!props.isModalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
);
}

How to not capture audio playback running on device when capturing new video

I am creating an app in expo/react-native where I am layering many videos captured by the user using expo-av, something like an acapella effect. Now if the user doesn't use headphones and tries to layer a new video listening to their previous recording(s), the sound of their previous recordings (playing on the phone speakers) comes as a disturbance on the new recording.
It seems to be possible to avoid this as we see when using Skype or Zoom one cannot hear feedback of their own voices on the sound coming in from the remote user.
It is possible using expo-av or any react native library, to cancel out speaker sound?
Sharing some code in case useful
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';
import {Video} from 'expo-av';
import { Ionicons } from '#expo/vector-icons';
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [cameraRef, setCameraRef] = useState(null);
const [videoRef,setVideoRef] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const [recording, setRecording] = useState(false);
const [videoSource, setVideoSource]= useState('http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4')
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const fireOnLoad=()=>{
}
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type} ref={ref => {
setCameraRef(ref) ;
}}>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
justifyContent: 'flex-end'
}}>
<View style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly'
}}>
<TouchableOpacity
style={{
flex: 0.1,
alignSelf: 'flex-end'
}}
onPress={() => {
setType(
type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
<Ionicons name={ Platform.OS === 'ios' ? "ios-reverse-camera" : 'md-reverse-camera'} size={40} color="white" />
</TouchableOpacity>
<TouchableOpacity style={{alignSelf: 'center'}} onPress={async() => {
if(cameraRef){
let photo = await cameraRef.takePictureAsync();
console.log('photo', photo);
}
}}>
<View style={{
borderWidth: 2,
borderRadius:60,
borderColor: 'white',
height: 50,
width:50,
display: 'flex',
justifyContent: 'center',
alignItems: 'center'}}
>
<View style={{
borderWidth: 2,
borderRadius:60,
borderColor: 'white',
height: 40,
width:40,
backgroundColor: 'white'}} >
</View>
</View>
</TouchableOpacity>
<TouchableOpacity style={{alignSelf: 'center'}} onPress={async() => {
if(!recording){
setRecording(true)
let video = await cameraRef.recordAsync();
//console.log('video', video);
setVideoSource(video.uri);
} else {
setRecording(false)
cameraRef.stopRecording()
}
}}>
<View style={{
borderWidth: 2,
borderRadius:60,
borderColor: 'red',
height: 50,
width:50,
display: 'flex',
justifyContent: 'center',
alignItems: 'center'}}
>
<View style={{
borderWidth: 2,
borderRadius:60,
borderColor: 'red',
height: 40,
width:40,
backgroundColor: 'red'}} >
</View>
</View>
</TouchableOpacity>
</View>
</View>
</Camera>
<Video
source={{ uri: videoSource }}
style={{ flex: 1 }}
useNativeControls='true'
resizeMode={Video.RESIZE_MODE_COVER}
onLoad={fireOnLoad}
onError={fireOnLoad}
isMuted={false}
/>
</View>
);
}