Pressing a button only dismisses the keyboard - react-native

I have a Modal which contains a TextInput and a Button. When the modal is opened, the keyboard appears which enables to enter text in the TextInput.
My problem is that when I press the button for the first time, the keyboard is dismissed but the button onPress method is not triggered.
import React from 'react';
import {
StyleSheet,
View,
Modal,
Text,
TextInput,
InteractionManager,
ScrollView,
TouchableWithoutFeedback,
TouchableOpacity,
Keyboard,
} from 'react-native';
import theme from '../../styles/theme.style';
import { MaterialCommunityIcons } from '#expo/vector-icons';
import I18n from '../../utils/i18n';
class RenameDrillModal extends React.Component {
// Enables to open the keyboard when the component is rendered
inputRef = React.createRef();
componentDidMount() {
this.focusInputWithKeyboard();
}
focusInputWithKeyboard() {
InteractionManager.runAfterInteractions(() => {
this.inputRef.current.focus();
});
}
render() {
return (
<View>
<Modal
animationType="fade"
transparent
visible
onRequestClose={() => {
this.props.close();
}}
>
{/* The sole purpose of the three following tags (TouchableOpacity, ScrollView, TouchableWithoutFeedback) is to close the modal when clicking outside of it */}
<TouchableOpacity
activeOpacity={1}
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}
onPressOut={() => {
this.props.close();
}}
>
<ScrollView directionalLockEnabled>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalTitleView}>
<Text style={styles.modalTitleText}>{`${this.props.drillTitle}`}</Text>
<View style={{ minWidth: '50%', flexDirection: 'row' }}>
<TextInput
style={{ minWidth: '90%', margin: 5, marginBottom: 0, flex: 1 }}
placeholder={I18n.t('drillEditor.drillManager.clickHereToRename')}
onChangeText={text => this.props.textModified(text)}
ref={this.inputRef}
/>
<MaterialCommunityIcons
name="check"
color={theme.COLOR_PRIMARY}
size={26}
onPress={() => {
console.log('Rename, onPress called');
this.props.close();
this.props.confirmNewName();
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
</ScrollView>
</TouchableOpacity>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
modalTitleView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 20,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
modalTitleText: {
fontWeight: 'bold',
fontSize: 20,
marginBottom: 15,
textAlign: 'center',
},
item: {
backgroundColor: theme.BACKGROUND_COLOR_LIGHT,
padding: 8,
borderRadius: 10,
marginVertical: 8,
marginHorizontal: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
});
export default RenameDrillModal;
The second press on the button works but do you know how I could both dismiss the keyboard and push the button by only pressing once?

Related

Problem with placing a pressable text in react native

I am working on a react native application and I was dealing with Modal and Pressable components, in fact the problem I got is not an error or a bug but I was trying to place a pressable text at the very right down side of the screen but I am struggling with styling a little bit so if anyone can give me a hand in this I would be so grateful.
this the code I wrote for the pop up form component:
import React from 'react';
import {View, Text, Modal, StyleSheet, Pressable, Alert} from 'react-native';
const PopUpModal = ({visible, onPress})=>{
return(
<View style={styles.container}>
<Modal
animationType="slide"
transparent={true}
visible={visible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.container}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={onPress}
>
<Text style={styles.textStyle}>Cancel</Text>
</Pressable>
</View>
</View>
</Modal>
</View>
)
}
const styles = StyleSheet.create({
container:{
width: "100%",
height : "100%"
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 5,
padding: 35,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
button: {
display: "flex",
borderRadius: 2,
padding: 10,
flexDirection:"row-reverse",
width: 65,
backgroundColor: "#051316",
},
buttonClose: {
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center",
alignItems: "flex-end"
},
modalText: {
marginBottom: 15,
flexDirection: "row-reverse"
}
})
export default PopUpModal
and this is what it looks like as an output of the above code example
output pic
Put your Pressable inside a View with the style property flexDirection:"row-reverse"
<View style={{flexDirection:"row-reverse"}}>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={onPress}
>
<Text style={styles.textStyle}>Cancel</Text>
</Pressable>
</View>

I am trying to implement text change and edit ends in TextInput using react-native but it's not quite working. Can any one help me?

I am trying to implement text change and edit ends in TextInput using react-native but it's not quite working.
See the Screenshot Here
Currently, when changing the price by touch input, the price is not affected when click off.
Here are my files
CartItem.js:
import React from "react";
import {
View,
TextInput,
Image,
TouchableOpacity,
StyleSheet,
Platform,
Alert,
} from "react-native";
//Colors
import Colors from "../../../utils/Colors";
//NumberFormat
import NumberFormat from "../../../components/UI/NumberFormat";
//Icon
import { MaterialCommunityIcons } from "#expo/vector-icons";
import CustomText from "../../../components/UI/CustomText";
//PropTypes check
import PropTypes from "prop-types";
export class CartItem extends React.PureComponent {
render() {
const { item, onAdd, onDes, onRemove } = this.props;
const AddItemHandler = async () => {
await onAdd();
};
const sum = +item.item.price * +item.quantity;
const checkDesQuantity = async () => {
if (item.quantity == 1) {
Alert.alert(
"Clear cart",
"Are you sure you want to remove the product from the cart?",
[
{
text: "Cancel",
},
{
text: "Yes",
onPress: onRemove,
},
]
);
} else {
await onDes();
}
};
return (
<View style={styles.container}>
<View style={styles.left}>
<Image
style={{
width: "100%",
height: 90,
resizeMode: "stretch",
borderRadius: 5,
}}
source={{ uri: item.item.thumb }}
/>
</View>
<View style={styles.right}>
<View
style={{ flexDirection: "row", justifyContent: "space-between" }}
>
<CustomText style={styles.title}>{item.item.filename}</CustomText>
<View>
<TouchableOpacity onPress={onRemove}>
<MaterialCommunityIcons name='close' size={20} color='#000' />
</TouchableOpacity>
</View>
</View>
<CustomText style={{ color: Colors.grey, fontSize: 12 }}>
Provided by Brinique Livestock LTD
</CustomText>
<NumberFormat price={sum.toString()} />
<View style={styles.box}>
<TouchableOpacity onPress={checkDesQuantity} style={styles.boxMin}>
<MaterialCommunityIcons name='minus' size={16} />
</TouchableOpacity>
Code that I would like to be fixed starts here.
<View>
<TextInput
keyboardType='numeric'
onEndEditing={AddItemHandler}
style={styles.boxText}>{item.quantity}</TextInput>
</View>
Code that I would like to be fixed ends here.
<TouchableOpacity
onPress={AddItemHandler}
style={styles.boxMin}>
<MaterialCommunityIcons name='plus' size={16} />
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
CartItem.propTypes = {
item: PropTypes.object.isRequired,
onAdd: PropTypes.func.isRequired,
onRemove: PropTypes.func.isRequired,
onDes: PropTypes.func.isRequired,
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 10,
height: 110,
borderBottomWidth: 1,
borderBottomColor: Colors.light_grey,
flexDirection: "row",
paddingVertical: 10,
alignItems: "center",
backgroundColor: "#fff",
paddingHorizontal: 10,
borderRadius: 5,
marginTop: 5,
},
left: {
width: "35%",
height: "100%",
alignItems: "center",
},
right: {
width: "65%",
paddingLeft: 15,
height: 90,
// overflow: "hidden",
},
title: {
fontSize: 14,
},
box: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
height: Platform.OS === "ios" ? 30 : 25,
backgroundColor: Colors.grey,
width: 130,
borderRadius: 5,
paddingHorizontal: 15,
marginTop: 5,
},
boxMin: {
width: "30%",
alignItems: "center",
},
boxText: {
fontSize: 16,
backgroundColor: Colors.white,
padding: 5,
},
});
Use onBlur instead of onEndEditing.
How should the input end triggered?
After a time?
When user hits enter?
When user taps anywhere to close software keyboard?
Instead of
onEndEditing={AddItemHandler}
Use:
onBlur={(e) => {AddItemHandler(e.nativeEvent.text)}}
And ensure that AddItemHandler can handle the value in e.nativeEvent.text.

About this.state function in React Native App

Hello this is my code. When I try to fill the text box then the error come i.e. ('this.setState is not a function.(In this.setState({emal:email)} this.setState is underfined').
Here is my code:
import React from 'react';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
TextInput,
TouchableHighlight,
Alert,
} from 'react-native';
export default function LoginScreen() {
onClickListener = (viewId) => {
Alert.alert("Alert", "You can't "+viewId);
}
return (
https://png.icons8.com/message/ultraviolet/50/3498db'}}/>
this.setState({email})}/>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}/>
<TextInput style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid='transparent'
onChangeText={(password) => this.setState({password})}/>
</View>
<TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={() => this.onClickListener('login')}>
<Text style={styles.loginText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('restore_password')}>
<Text>Forgot your password?</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('register')}>
<Text>Register</Text>
</TouchableHighlight>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DCDCDC',
},
inputContainer: {
borderBottomColor: '#F5FCFF',
backgroundColor: '#FFFFFF',
borderRadius:30,
borderBottomWidth: 1,
width:250,
height:45,
marginBottom:20,
flexDirection: 'row',
alignItems:'center'
},
inputs:{
height:45,
marginLeft:16,
borderBottomColor: '#FFFFFF',
flex:1,
},
inputIcon:{
width:30,
height:30,
marginLeft:15,
justifyContent: 'center'
},
buttonContainer: {
height:45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
},
loginButton: {
backgroundColor: "#00b5ec",
},
loginText: {
color: 'white',
}
});
That is the problem
export default function LoginScreen()
Change it to the
export default class LoginScreen extends Component
For using state, it must a stateful component rather than stateless component, So you have to change your functional component into Class.
change
export default function LoginScreen()
to
export default class LoginScreen extends React.Component
In react-native setState function has syntax
this.setState({someField:someValue})
you are using wrong syntax there, you have to give state name and value
this.setState({email})
this.setState({password})
these line should be like -
this.setState({ email: value })
this.setState({password: value })
if you want to use functional components you can use the UseState hook like this
by importing and initializing the state as shown below:
import React,{useState} from 'react';
export default function LoginScreen() {
const [email,setEmail]=useState(initialValues);
//setEmail function can be used for changing the state
}
use can see the usage of the useState here [https://reactjs.org/docs/hooks-state.html]
hope this helps for you
if you want to use functional components use react hooks,
otherwise use class component as below.
import React, { Component } from 'react';
import { Image, StyleSheet, Text, View, TextInput, TouchableHighlight, Alert } from 'react-native';
export default class LoginScreen extends Component {
onClickListener = viewId => {
Alert.alert('Alert', "You can't " + viewId);
};
render() {
return (
<View>
<View style={styles.inputContainer}>
<Image
style={styles.inputIcon}
source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}
/>
<TextInput
style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid="transparent"
onChangeText={password => this.setState({password})}
/>
</View>
<TouchableHighlight
style={[styles.buttonContainer, styles.loginButton]}
onPress={() => this.onClickListener('login')}>
<Text style={styles.loginText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => this.onClickListener('restore_password')}>
<Text>Forgot your password?</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => this.onClickListener('register')}>
<Text>Register</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DCDCDC',
},
inputContainer: {
borderBottomColor: '#F5FCFF',
backgroundColor: '#FFFFFF',
borderRadius: 30,
borderBottomWidth: 1,
width: 250,
height: 45,
marginBottom: 20,
flexDirection: 'row',
alignItems: 'center',
},
inputs: {
height: 45,
marginLeft: 16,
borderBottomColor: '#FFFFFF',
flex: 1,
},
inputIcon: {
width: 30,
height: 30,
marginLeft: 15,
justifyContent: 'center',
},
buttonContainer: {
height: 45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20,
width: 250,
borderRadius: 30,
},
loginButton: {
backgroundColor: '#00b5ec',
},
loginText: {
color: 'white',
},
});

React Native can't click TouchableOpacity or TextInput

In my React Native project I have a TextInput and a TouchableOpacity component at the top of the screen that for some reason cannot be clicked. It worked at some point while I was working on the project, but for some reason it no longer recognizes clicks or key events. The component is as follows:
import React, { Component } from "react";
import {
AsyncStorage,
Dimensions,
FlatList,
Platform,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from "react-native";
import styles from "./style/styles";
import NotificationBar from "./components/NotificationBar";
export default class App extends Component {
constructor(props) {
super(props);
this.data = [];
this._initData();
}
_initData() {
for (let i = 0; i < 500; i++) {
this.data.push({
// key: i,
id: "ABC" + i,
name: "Random Name",
value: 50 * i
});
}
}
_renderItem = ({ item }) => {
return (
<View style={styles.itemContainer}>
<Text style={styles.textItem}>{item.id}</Text>
</View>
);
};
render() {
return (
<View>
<NotificationBar />
<View style={{ flex: 1, flexDirection: "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<View
style={{
width: (Dimensions.get("window").width / 3) * 2,
height: 50,
backgroundColor: "white"
}}
>
<TextInput
placeholder="New List Name"
style={styles.textInputStyle}
/>
</View>
<View
style={{
width: Dimensions.get("window").width / 3,
height: 50,
backgroundColor: "#4ce31e"
}}
>
<TouchableOpacity
style={styles.button}
onPress={this.testSetStorage}
>
<Text> Create List </Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={{ paddingTop: 50 }}>
<FlatList
data={this.data}
renderItem={this._renderItem}
style={{ alignSelf: "stretch" }}
keyExtractor={(item, index) => item.id}
/>
</View>
</View>
);
}
}
The style sheet is:
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
statusBarBackground: {
height: 20,
backgroundColor: 'white',
},
textInputStyle: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
textAlign: 'center',
borderWidth: 1,
borderRadius: 6,
},
button: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: 100,
paddingLeft: 20,
},
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10
},
});
My best guess is that it the issue would have something to do with the parent View components that the TouchableOpacity and TextInput components are in, but I'm not sure. How can I get those components to recognize clicks and respond to them? I'm running on an iPhone 7 emulator.
You have not defined testSetStorage function in your component.
You need to testSetStorage = () => {console.log("Tapped")} outside render function.

React navigation- Wrap button in TabBar

I'm new in React Native and i'm trying to do the TabBar in the image. My problem is to put a button in the tabbar. If someone can help me or have an idea to create this tabbar it could be really nice.
THX
you can check
this link. One of the props to pass TabNavigator is tabBarComponent. If you do not want the default styling or have to make custom tabBar you can specify the how the component should look.
In your case this should work.
import React from 'react';
import {View, Text, TouchableOpacity, Dimensions} from 'react-native';
import {TabNavigator} from 'react-navigation';
import Tab1Screen from '../components/tab1Screen';
import Tab2Screen from '../components/tab2Screen';
var {height, width} = Dimensions.get('window');
const mainRoutes = TabNavigator({
Tab1: {screen: Tab1Screen},
Tab2: {screen: Tab2Screen}
},
{
tabBarComponent:({navigation}) => (
<View style={{flex: 0.1, borderColor: 'green', borderWidth: 1}}>
<View style={{flexDirection:'row', justifyContent: 'space-around', alignItems: 'center', paddingTop: 15}}>
<View style={{width: 40, height: 40, borderRadius: 20, borderColor: 'red', borderWidth: 1, position: 'absolute', left: width/2.5, bottom:13 }}></View>
<TouchableOpacity onPress={() => navigation.navigate('Tab1')}>
<Text>Tab1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('Tab2')}>
<Text>Tab2</Text>
</TouchableOpacity>
</View>
</View>
)});
export default mainRoutes;
I had to do something similar. I'm using React Navigation v5 and in my case, the button had to execute a custom action instead of navigating to a tab. So this is what I did:
import styles from './styles';
// Other needed imports...
// ...
<Tab.Screen
name="Add Recipe"
component={() => null}
options={{
tabBarButton: () => (
<TouchableOpacity
style={styles.addIconWrapper}
onPress={() => {
// Your custom action here
}}
>
<View style={styles.addIconBackground}>
<Image source={assets.add} style={styles.addIconImage} />
</View>
</TouchableOpacity>
),
}}
/>;
And inside styles.js:
// ...
addIconWrapper: {
width: '20%',
justifyContent: 'center',
alignItems: 'center',
},
addIconBackground: {
marginTop: -30,
backgroundColor: '#85c349',
borderColor: 'white',
shadowOffset: { width: 2, height: 2 },
shadowColor: '#999',
shadowOpacity: 0.5,
borderRadius: 1000,
width: 42,
height: 42,
justifyContent: 'center',
alignItems: 'center',
},
addIconImage: {
tintColor: 'white',
},
Final result