Modal not getting opened on clicking the image of gallery component - javascript

I'm trying to open a model when I click on the image component in the gallery. Here I'm not getting the "flagImage" variable updated in onPress method of TouchableOpacity or the modal component is not getting the updated value of "flagImage" when onPress of TouchableOpacity changes its value. I need help here. The modal doesn't open at all whenever I touch the image component. It just does nothing :( Below is the code for gallery.component.js:
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], flagImage=true}) => (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<TouchableOpacity
onPress={()=> {
flagImage = !flagImage;
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={styles.galleryImage}/>
</TouchableOpacity>
<Modal visible={flagImage} onPress={() => {console.log('Modal: "'+flagImage+'"');flagImage = !flagImage;}} onRequestClose={() => flagImage = ! flagImage}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
);

You can make use of useState hook to convert the props into a state where you can update them.
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], lflagImage=false}) => {
const [flagImage, setflagImage] = React.useState(lflagImage);
return (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={flagImage?styles.galleryImageContainer:styles.galleryImageContainerView} key={uri}>
<TouchableOpacity
onPress={()=> {
setflagImage(prevData => !prevData)
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={flagImage?styles.galleryImage:styles.galleryImageLarge}/>
</TouchableOpacity>
<Modal visible={flagImage} onRequestClose={() => setflagImage(prevData => !prevData)}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
)
}

Related

react-native swipeable gesture not working on android?

I am doing a react native course with Mosh (https://codewithmosh.com/). I am using expo. I am very new to react native and don't really know what I am doing, but I know my code should work. I double-checked my code against his and even went so far as to copy my project over to a friends mac and see if the code works on ios (as mosh is running his code on the ios simulator). On the ios simulator, my code runs perfectly, but on android, nothing happens.
Here is where I implement the swipeable itself:
import React from 'react';
import { StyleSheet, View, Image, TouchableHighlight } from 'react-native';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import AppText from './AppText';
import colors from '../config/colors';
function ListItem({title, subtitle, image, onPress, renderRightActions}) {
return (
<Swipeable renderRightActions={renderRightActions} >
<TouchableHighlight underlayColor={colors.light} onPress={onPress} >
<View style={styles.container} >
<Image style={styles.image} source={image} />
<View>
<AppText style={styles.title} >{title}</AppText>
<AppText style={styles.subTitle}>{subtitle}</AppText>
</View>
</View>
</TouchableHighlight>
</Swipeable>
);
}
I then export this to a different screen:
function MessagesScreen(props) {
return (
<Screen>
<FlatList
data={messages}
keyExtractor={message => message.id.toString}
renderItem={({ item }) => (
<ListItem
title={item.title}
subtitle={item.description}
image={item.image}
onPress={() => console.log('message selected', item)}
renderRightActions={ListItemDeleteAction}
/>
)}
ItemSeparatorComponent={ListItemSeparator}
/>
</Screen>
);
}
the listItemDelete action I am passing into the renderRightActions prop can be seen here:
function ListItemDeleteAction(props) {
return (
<View style={styles.container} ></View>
);
}
Alright so, I found a solution by wrapping the swipeable in a gestureHandlerRootView.
import { GestureHandlerRootView, Swipeable } from "react-native-gesture-handler";
import AppText from "./AppText";
import colors from "../config/colors";
function ListItem({ title, subtitle, image, onPress, renderRightActions }) {
return (
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<TouchableHighlight underlayColor={colors.light} onPress={onPress}>
<View style={styles.container}>
<Image style={styles.image} source={image} />
<View>
<AppText style={styles.title}>{title}</AppText>
<AppText style={styles.subTitle}>{subtitle}</AppText>
</View>
</View>
</TouchableHighlight>
</Swipeable>
</GestureHandlerRootView>
);
}
I found a solution by wrapping the swipeable in a gestureHandlerRootView.
import { GestureHandlerRootView } from "react-native-gesture-handler";
import AppText from "./AppText";
import colors from "../config/colors";
function ListItem({ title, subtitle, image, renderRightActions }) {
return (
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<View style={styles.main}>
<Image style={styles.img} source={image} />
</View>
</Swipeable>
</GestureHandlerRootView>
);
}
try this option...
import {
GestureHandlerRootView,
Swipeable,
} from "react-native-gesture-handler";
then wrap on <Swipeable>..</Swipeable>
look example below
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<TouchableHighlight underlayColor={Colors.ccc} onPress={onPress}>
<View style={styles.view}>
<Image style={styles.image} source={image} />
<View style={styles.details}>
<Txt style={styles.title}>{title}</Txt>
<Txt style={styles.subtitle}>{subtitle}</Txt>
</View>
</View>
</TouchableHighlight>
</Swipeable>
</GestureHandlerRootView>

How to show an item from an array in json to a react native modal unique on button click

I have an array of data stored in a JSON file. It has ID, title and description. Now I have listed out the titles in my ReactNative app. I want to display the content of each title on a modal. How can I do that?
Below is my code where the modal will come up, but the description won't appear on the modal. Instead it gives an error that it's not defined.
import { StatusBar } from "expo-status-bar";
import React, { useState } from "react";
import {
Modal,
Platform,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
export default function App() {
const data = require("./dummyData.json");
let modalData = [];
const [showStanzas, SetshowStanzas] = useState(false);
const onpressHandler = function (a, b) {
modalData = data[b];
SetshowStanzas(true);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.headingView}>
<Text style={styles.heading}></Text>
</View>
<ScrollView>
<View style={styles.container2}>
<View style={styles.container3}>
{data.map((datas, id) => {
return (
<View key={id}>
<Text
style={styles.hymnTitle}
onPress={() => {
onpressHandler(true, id);
}}
>
{datas.id}. {""}
{datas.title}{" "}
</Text>
</View>
);
})}
<Modal
animationType={"slide"}
visible={showStanzas}
onRequestClose={() => SetshowStanzas(false)}
>
<View>
<Text style={styles.desc}> {modalData.description} </Text>
</View>
</Modal>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
Migrate the local variable modalData to a React state
const [mobileData, setMobileData] = useState();
Then store the selected index data on the on onpressHandler
const onpressHandler = function (a, b) {
setMobileData(data[b]);
SetshowStanzas(true);
};
Your modal code should work afterwards

React Native: I can't set a TextInput value from a 'child' screen

I am working in React Native and I want to set a value in a non-editable TextInput. The value is written on a screen that I am navigating to. Meaning; "parent" screen has the empty input -> I navigate to a "child" screen in which I can enter the value in another TextInput. When I have done that I want to press "OK" and go back to the "parent" screen where the value is displayed.
I have read the documentation as thoroughly as I could, but I still can't get it to work. I can set the value in the "child" screen, but the value is not updated when I navigate back to the parent.
Parent screen
Disregard the code related to equipment, since it will assimilate the barcode logic
import React, { useState } from 'react'
import { Text, TouchableOpacity, View, Image, TextInput } from 'react-native'
import styles from './styles';
import { IMAGE } from '../../constants/Images'
import { CustomHeader } from '../../CustomHeader'
export default function SamplingScreen({ navigation, route }) {
//const [barcodeData, setBarcodeData] = useState('32231321')
const [equipmentID, setEquipmentID] = useState('')
//Guarding against undefined value
const barcode = route.params?.barcode ?? 'Barcode'
return (
<View style={styles.container}>
<CustomHeader title="Sample Oil" navigation={navigation} isHome={true} ></CustomHeader>
<View style={styles.contentContainer}>
<Image
style={styles.logo}
source={IMAGE.ICON_LOGO}
/>
<Text>Send an oil sample for analysis</Text>
<Text>Start by linking a bottle with its barcode</Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('BottleID')} /*barcodeData={setBarcodeData}*/ >
<Text style={styles.buttonText} >Link Bottle</Text>
</TouchableOpacity>
<Text>Please link the equipment from which the sample was taken</Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('EquipmentID')} equipmentID={setEquipmentID} >
<Text style={styles.buttonText} >Link Equipment</Text>
</TouchableOpacity>
<Text>This is the bottle barcode</Text>
<TextInput
editable={false}
style={styles.input}
defaultValue={barcode}
value={barcode}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<Text>This is the equipment barcode</Text>
<TextInput
editable={false}
style={styles.input}
defaultValue={equipmentID}
value={equipmentID}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Accept</Text>
</TouchableOpacity>
</View>
</View>
)
}
Child screen
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, TextInput } from 'react-native';
import { CustomHeader } from '../../../CustomHeader'
import styles from './styles'
export default function SetBottleIDScreen({ navigation, route }) {
const [barcodeData, setBarcodeData] = useState('')
console.log(barcodeData)
return (
<View style={styles.container} >
<CustomHeader title="Bottle ID" isHome={false} navigation={navigation} ></CustomHeader>
<Text style={{ marginTop: 30, marginBottom: 30 }} > Set barcode for sampling bottle </Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Camera')}>
<Text style={styles.buttonText}>Scan Barcode</Text>
</TouchableOpacity>
<Text style={{ marginTop: 60, marginBottom: 10 }} >Insert Barcode</Text>
<TextInput
style={styles.input}
placeholder='Barcode'
placeholderTextColor="#aaaaaa"
onChangeText={(text) => setBarcodeData(text)}
value={barcodeData}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Sampling', { screen: 'Sampling', params: { barcode: barcodeData }, merge: true })}>
<Text style={styles.buttonText} >OK</Text>
</TouchableOpacity>
</View>
);
}
I am using React Navigation 5.x. I am pretty sure that the value has to be parsed as a parameter with route, but something isn't working as intended.
I solved the issue.
The syntax for setting the parameters were wrong.
It should look like this in stead:
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Sampling', { barcode: barcodeData })}>
<Text style={styles.buttonText} >OK</Text>
</TouchableOpacity>

React-native autocomplete issue ("Objects are not valid as a Reach child")

I'm trying to use Autocomplete in React-native but I'm obviously doing something wrong.
Here a minimal example of code showing what I'm doing:
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Autocomplete from 'react-native-autocomplete-input';
const DATA =
[{"id": 1,"title": "test1"},{"id": 2,"title": "test2"},{"id": 3,"title": "test3"}]
const App = () => {
const [query, setQuery] = useState('');
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
data={DATA}
value={query}
onChangeText={setQuery}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{item.title}
</Text>
</TouchableOpacity>
)}
/>
</View>
</SafeAreaView>
);
};
I reduced the code to the very minimum.
However, I keep getting error:
"Objecs are not valid as a React child (found: object with keys {id,title}"
It seems I'm missing something very obvious about renderItem (I guess), but since I'm stuck since a few hours, another eye could spot what I'm doing wrong.. any help would be appreciated, thanks.
Your destructuring was wrong. do like below {id,title}. renderItem is array of iteration so its look like object.
renderItem={({title,id}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{title}
</Text>
</TouchableOpacity>
)}
I actually found the answer.
It seems, I haven't read correctly the list of props for Autocomplete: in fact, renderItem must be passed inside an option called "flatListProps".
Correct code is below:
import React, {useState, useEffect} from 'react';
import {
SafeAreaView,
StyleSheet,
TextInput,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Autocomplete from 'react-native-autocomplete-input';
const DATA =
[{"id": 1,"title": "test1"},{"id": 2,"title": "test2"},{"id": 3,"title": "test3"}]
const App = () => {
const [query, setQuery] = useState('');
return (
<SafeAreaView style={{flex: 1}}>
<View style={styles.container}>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
data={DATA}
value={query}
onChangeText={setQuery}
flatListProps={{
keyboardShouldPersistTaps: 'always',
keyExtractor: (item) => item.id,
renderItem: ( ({item}) => (
<TouchableOpacity
onPress={() => {}}>
<Text>
{item.title}
</Text>
</TouchableOpacity>
))
}}
/>
</View>
</SafeAreaView>
);
};
renderItem={({ item, i }) => (
<TouchableOpacity key={i} onPress={() => ()}>
<Text>{item.label}</Text>
</TouchableOpacity>
)}
You have to pass the index to key.

TouchableOpacity effect on Text

I want my Menu text to have the same effect that TouchableOpacity does on touch.And open a new screen
***Settings.js***
import React, { useState } from 'react'
import{StyleSheet,Text,View,TextInput} from 'react-native'
import { TouchableOpacity,FlatList,ScrollView } from 'react-native-gesture-handler'
export default function App(){
const[menu,menupeople]=useState([
{name:'My Account',key:1},
{name:'Notification Settings',key:2},
{name:'Clear Cache',key:3},
{name:'Legal Information',key:4},
{name:'Rate App Tak',key:5},
{name:'Version',key:6},
{name:'About',key:7},
])
return(
<View style={styles.container}>
<ScrollView>
{menu.map((item)=>{
return(
<View
key={item.key}
>
<Text style={styles.item}
>{item.name}</Text>
</View>
)
})}
</ScrollView>
</View>
)
}
const styles=StyleSheet.create({
container:{
flex:1,
backgroundColor:'#fff',
paddingTop:40,
paddingHorizontal:20,
alignItems:'center'
}
})
Is there any way to do this i am first time applying touchable opacity to a menu of items and each of them opens a new screen
You can use the touchableopacity instead of the View to wrap the menu item like below
{menu.map((item)=>{
return(
<TouchableOpacity onPress={()=>alert(item.name)}
key={item.key}
>
<Text style={styles.item}
>{item.name}</Text>
</TouchableOpacity>
)
})}
Here I've put an alert you can change it to your navigation code.
And please import the TouchableOpacity from react native
import { TouchableOpacity } from "react-native";

Categories

Resources