TouchableHighlight does not work when I nested it in Modal - react-native

I used touchablehighlight in other screen (not in modal) they worked properly.But I don't understand why its doesnt work properly when I put it in modal. If I put Button, it works.
Here is a part of my code:
Please help me !
import React,{useState} from 'react'
import {
View,
Text,
Modal,
Button
} from 'react-native';
import { TouchableHighlight } from 'react-native-gesture-handler';
const Icons = () => {
const [modalVisible, setModalVisible] = useState(true);
console.log(modalVisible)
return (
<View >
<TouchableHighlight
onPress={()=>setModalVisible(!modalVisible) }
>
<Text>Son</Text>
</TouchableHighlight>
<Modal
visible={modalVisible}
>
<View >
<View style={{marginBottom: 100, }}>
<Text style={{fontSize:30}} >Hoşgeldiniz</Text>
</View>
<View style={''}>
<TouchableHighlight
onPress={ () => setModalVisible(!modalVisible) }
>
<Text>Sağol</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
)
}

I had the same problem as well.
Import TouchableHighlight from 'react-native'.
But I dont know why it does not work when I import from gesture.

Related

Expo / TouchableOpacity onPress() not responding

I'm trying to reproduce a pomodoro app from an online course.
I've been looking at my code for several hours, going back and forth with the course, but can't find my error.
TouchableOpacity or Pressable used in RoundedButton component doesn't trigger onPress()
I tried different command to test if my logic with setStarted was flawe, without success.
Anyone can help me find my bug ?
Here is the link to the expo : https://snack.expo.dev/#battlepoap/focus-time
RoundedButton.js:
import React from 'react';
import { TouchableOpacity, Text, StyleSheet, View } from 'react-native';
export const RoundedButton = ({
style = {},
textStyle = {},
size = 125,
...props
}) => {
return (
<View>
<TouchableOpacity style={[styles(size).radius, style]}>
<Text style={[styles(size).text, textStyle]}>{props.title}</Text>
</TouchableOpacity>
</View>
);
};
const styles = (size) =>
StyleSheet.create({...});
Example with Focus.js where we add a task by pressing on the RoundedButton :
import React, { useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { TextInput } from 'react-native-paper';
import { RoundedButton } from '../../components/RoundedButton';
import { fontSizes, spacing } from '../../utils/sizes';
export const Focus = ({ addSubject }) => {
const [tempSubject, setTempSubject] = useState(null);
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>What do you want to focus on ?</Text>
<View style={styles.inputContainer}>
<TextInput
style={{ flex: 1, marginRight: spacing.sm }}
onSubmitEditing={({ nativeEvent }) => {
setTempSubject(nativeEvent.text);
}}
/>
<RoundedButton
size={50}
title="+"
onPress={() => addSubject = tempSubject}
/>
</View>
</View>
</View>
);
};
sic In the additional files there was ....
One thing we however need to add in order to make sure the button triggers is the onPress method. This method allows us to trigger the touch event of the user. Don't forget it!!
<TouchableOpacity style={[styles(size).radius, style]}>
<Text
style={[styles(size).text, textStyle]}
onPress={props.onPress}>
{props.title}
</Text>
</TouchableOpacity>

How do I display the numbers 0 to 10 in react native without repetition each time I click on the output?

I want the numbers 0 to 10 to be repeated only once and then start counting from 0 to 10 again.
enter image description here
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
SafeAreaView,
TouchableOpacity,
} from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
export class CertificationScreen extends Component{
constructor(props) {
super(props);
}
render() {
const count = 0;
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.item}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Forms', {itemId: count + 1 })}>
<Ionicons style={styles.icons} name="arrow-back" size={24} color="#0064FE" />
<Text style={{fontSize: 24}}>Text</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);}
}
I researched a lot, but I could not solve this problem.
please guide me.
Yes, this is exactly what I want, to add a number by tapping TouchableOpacity. And send this data to my class component via props (itemId). But after making changes, I get this error: Too many re-renders. React limits the number of renders to prevent an infinite loop. Do you know a better way I can use it?
import React from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
SafeAreaView,
TouchableOpacity,
} from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
export function CertificationScreen() {
let [counter, setCounter] = React.useState();
if (counter < 10) {
setCounter(prev => prev + 1);
} else {
setCounter(0);
}
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.item}>
<TouchableOpacity onPress={() =>
navigation.navigate('Forms', {itemId: setCounter })}>
<Ionicons style={styles.icons} name="arrow-back" size={24} color="#0064FE" />
<Text style={{fontSize: 24}}>Text</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
enter image description here
This is exactly what I want:
let [counter, setCounter] = React.useState ();
if (counter <10) {
setCounter (prev => prev + 1);
} else {
setCounter (0);
}
After clicking on touchableOpacity, I want the data from the counter to be transferred via prop and navigation to the next page where the data is displayed in .
enter image description here
I created a snack example to better understand this issue, please let me know if there is an error in the process.
https://snack.expo.dev/#devsaeedhabibi/certification
Update:
How can I integrate Button and TouchableOpacity?
<Button title='Certification' onPress={() => {
if(counter < 10) {
setCounter(prev => prev + 1)
}else {
setCounter(1)
}
}} />
<TouchableOpacity onPress={() => navigation.navigate('Forms', {itemId: counter })}>
<Ionicons style={styles.icons} name="arrow-back" size={24} color="#0064FE" />
<Text style={{fontSize: 24, alignSelf: 'center'}}>Certification</Text>
</TouchableOpacity>
Take a look at this snack:
https://snack.expo.dev/#devsaeedhabibi/certification-2
Edit:
Using a Pressable component solved the problem.
<Pressable onPressIn={()=> {if(counter < 10) {setCounter(prev => prev + 1)}else{setCounter(1)}}}
onPress={() => navigation.navigate('Forms', {itemId: counter })}>
onPressIn:
Called immediately when a touch is engaged, before onPressOut and onPress.
onPressOut:
Called when a touch is released.
onPress:
Called after onPressOut.
This is exactly what I wanted.
Take a look at this snack:
https://snack.expo.dev/#devsaeedhabibi/certification-v3
Thank you for your attention to this matter.
I think this is what you want;
import React, {useState} from 'react'
import {View, Text, Button} from 'react-native'
const App = () => {
let [counter, setCounter] = useState(0)
return (
<View>
<Button title='counter' onPress={() => {
if (counter < 10) {
setCounter(prev => prev + 1)
} else {
setCounter(0)
}
}}/>
<Text>{counter}</Text>
</View>
)
}
export default App;

react native keyboard dismiss not working

can anyone explain me why keyboard dismiss not works ? No errors and nothing happens.
In my last project it works, but not there. What do I am wrong?
Code:
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, TextInput, TouchableOpacity, KeyboardAvoidingView, ScrollView, Dimensions, Keyboard } from 'react-native';
import { AntDesign } from '#expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const Home = () => {
const [searchInput, setSearchInput] = useState('');
return (
<KeyboardAvoidingView onPress={() => Keyboard.dismiss()} style={styles.container}>
<LinearGradient
style={styles.header}
colors={['blue', 'red', 'orange']}
>
<View style={{alignItems: 'flex-end'}}>
<TouchableOpacity>
<AntDesign style={{textAlign: 'right'}} name="pluscircleo" size={42} color="#fff" />
</TouchableOpacity>
</View>
<View style={styles.headerBottom}>
<Text style={styles.headerText}>Treffpunkt</Text>
<TextInput
placeholder="Gebe deinen Code ein"
value={searchInput}
onChangeText={value => setSearchInput(value)}
style={styles.searchInput}
/>
</View>
</LinearGradient>
</KeyboardAvoidingView>
)
};
As Konstantin had mentioned in the comment, KeyboardAvoidingView does not have an onPress event.
You can have a child element before the gradient that will handle the press for you.
You can refer to the expo example here
<KeyboardAvoidingView
style={styles.container}>
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<LinearGradient
style={styles.header}
colors={['blue', 'red', 'orange']}>
<View style={{ alignItems: 'flex-end' }}>
...
</View>
</LinearGradient>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>

How to open Modal from another component in react-native

I have tried to open Modal from another component in react-native, but modal is not open. so please help me if have any solution. this is my code
modal.js
import React from './node_modules/react';
import { View, Text } from 'react-native';
const ProfileModal = () => {
return (
<View>
<Text>HELLO TEXT</Text>
</View>
);
}
export default ProfileModal;
----------------------------------------
header.js
import ProfileModal from './ProfileModal';
import { Image, View, TouchableOpacity, Text } from 'react-native';
import Modal from 'react-native-modal';
const openLoginPopup = () => {
return (
<TouchableOpacity onPress={() => this.openModal}>
<Text> Login </Text>
</TouchableOpacity>
)
}
const openModal = () => {
return (
<Modal isVisible={true}>
<ProfileModal />
</Modal>
)
}
Thanks,
In that case, react-native-modal provide callback onBackdropPress, onBackButtonPress to close.
You can use it like this:
const ProfileModal = ({ open, onClose }) => {
return (
<Modal isVisible={open} onBackButtonPress={onClose} onBackdropPress={onClose}>
<View>
<Text>HELLO TEXT</Text>{' '}
</View>
</Modal>
)
}
Then pass onClose function when using it:
<ProfileModal open={open} onClose={()=> setOpen(false)} />
It's like you write the content modal in modal file. So you can do it something like:
modal.js
import React, {useState} from 'react';
import { View, Text } from 'react-native';
const ProfileModal = () => {
return (
<View>
<Text>HELLO TEXT</Text>
</View>
);
}
export default ProfileModal;
----------------------------------------
header.js
import ProfileModal from './ProfileModal';
import { Image, View, TouchableOpacity, Text } from 'react-native';
import Modal from 'react-native-modal';
const Header = () => {
const [open, setOpen] = useState(false)
return (
<View>
{/* some content */}
{/* btn trigger */}
<TouchableOpacity onPress={() => setOpen(true)}>
<Text> Login </Text>
</TouchableOpacity>
<Modal isVisible={open}>
<ProfileModal />
</Modal>
</View>
)
}
or
modal.js
import React, {useState} from 'react';
import { View, Text } from 'react-native';
const ProfileModal = ({ open }) => {
return (
<Modal isVisible={open}>
<View>
<Text>HELLO TEXT</Text>
</View>
</Modal>
);
}
export default ProfileModal;
----------------------------------------
header.js
import ProfileModal from './ProfileModal';
import { Image, View, TouchableOpacity, Text } from 'react-native';
import Modal from 'react-native-modal';
const Header = () => {
const [open, setOpen] = useState(false)
return (
<View>
{/* some content */}
{/* btn trigger */}
<TouchableOpacity onPress={() => setOpen(true)}>
<Text> Login </Text>
</TouchableOpacity>
<ProfileModal open={open} />
</View>
)
}
First of all openModal method is not part of openLoginPopup so remove this before openModal method.
Just use directly like below,
const openLoginPopup = () => {
return (
<TouchableOpacity onPress={openModal}>
<Text> Login </Text>
</TouchableOpacity>
)
}
Second issue was that you also don't need arrow function in onPress event until you want to pass some parameters in openModal method. You can directly pass the method name and it will work.

I can't trigger the modal component to open from a different component

I declared a Modal component in a separate js file and I'm trying to make it appear when an onPress event happens. I can't seem to be able to toggle that.
I Googled and found React Native open modal from different component but either I'm not getting something or that doesn't work for me.
I have the following modal.js:
import React, {Component} from 'react';
import {
Modal,
StyleSheet,
Text,
TouchableHighlight,
View,
Alert
} from 'react-native';
import config from '../config/colors';
export default class ModalWindow extends Component {
state = {
modalVisible: false,
};
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View style={styles.container}>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
onDismiss={() => {
console.log('Modal has been closed.');
}}>
<View style={styles.container}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text>Hide Modal!</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight
onPress={() => {
this.setModalVisible(true);
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
marginTop: 22
}
});
And inside a separate file I have:
import Modal from '../components/modal';
and declared the component inside my render as such
... other stuff ...
<View style={styles.modalContainer}>
<Modal isModalVisible={this.state.modalVisible}></Modal>
</View>
... other stuff ...
finally, I have a button set such that this gets called: onPressAvatar={this.onPressAvatar}
and that method is:
onPressAvatar = props => {
console.log("press avatar");
this.setState({modalVisible: true});
}
I know the onPress works because the console.log() gets triggered but the modal doesn't appear. What am I missing?
You need to use props to open/close your modal like this:
import React, {Component} from 'react';
import {
Modal,
StyleSheet,
Text,
TouchableHighlight,
View,
Alert
} from 'react-native';
import config from '../config/colors';
export default class ModalWindow extends Component {
render() {
return (
<View style={styles.container}>
<Modal
animationType="fade"
transparent={false}
visible={this.props.isModalVisible}
onDismiss={() => {
console.log('Modal has been closed.');
}}>
<View style={styles.container}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight
onPress={() => {
this.props.close();
}}>
<Text>Hide Modal!</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight
onPress={() => {
this.setModalVisible(true);
}}>
<Text>Show Modal</Text>
</TouchableHighlight>
</View>
);
}
}
Note that I change this.state.modalVisible to this.props.modalVisible and I remove the methods that set the states
Here you pass your state values
... other stuff ...
<View style={styles.modalContainer}>
<Modal isModalVisible={this.state.modalVisible} close={this.setState({modalVisible: false})}></Modal>
</View>
... other stuff ...
And now your component is controlled by your Parent component that changes its own state and propagate to your Modal.
A component has props and states, props are immutable objects that the component receives when you pass data by setting attributes like <Modal isModalVisible={value} />. They become available to your component by the property this.props. On the other hand the State property is used to control the internal state of the component and each state change using this.setState causes a new rendering call. So in your code we need to set Parent component State to notify all the components children that there are changes. Then your Modal component will call its own method render to show or hidden the modal box.