I have two very simple components and the pressables I have in my Start component just won't work, not the navigation or the console.log(), I can't even inspect them with the element inspector... I am using ImageBackground of react native for the first time so i don't know if this has something to do with it? Although, i did try removing it and i still couldn't press anything...
Here is my code for the Start component:
import React from 'react';
import {ImageBackground, Pressable, StyleSheet, Text, View} from 'react-native';
import { normalize } from '../../utils/helper';
import { colors } from '../../utils/styles';
const image = require('../../assets/images/start-page/start-page-background.png');
export default function Start({navigation}) {
const handleStartPress = () => {
console.log('hi');
navigation.navigate('Home');
};
return (
<View style={styles.container}>
<ImageBackground source={image} style={styles.image}>
<Pressable style={styles.startButton} onPress={() => handleStartPress()}>
<Text style={styles.startText}>Έναρξη</Text>
</Pressable>
<View style={styles.footer}>
<Pressable style={[styles.footerPressable, styles.conditions]}><Text style={styles.footerText}>blah</Text></Pressable>
<Text style={styles.code}>blah</Text>
<Pressable style={[styles.footerPressable, styles.policy]} onPress={() => console.log('policy')}><Text style={styles.footerText}>blah</Text></Pressable>
</View>
</ImageBackground>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
},
startButton: {
backgroundColor: colors.main.blue,
borderRadius: normalize(10),
paddingHorizontal: normalize(40),
paddingVertical: normalize(12),
alignSelf: 'center',
position: 'absolute',
bottom: normalize(180),
},
startText: {
color: 'white',
fontSize: normalize(30),
},
footer: {
paddingVertical: normalize(10),
position: 'absolute',
bottom: normalize(15),
},
conditions: {
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingLeft: normalize(10),
paddingRight: normalize(10),
},
policy: {
paddingLeft: normalize(10),
//zIndex: 999,
},
footerText: {
fontSize: normalize(16),
lineHeight: normalize(16),
color: 'black',
},
code: {
color: colors.main.blue,
fontWeight: '700',
fontSize: normalize(16),
lineHeight: normalize(16),
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingHorizontal: normalize(10),
},
});
I ran your code and it works fine. But I don't have any more information on your project (such as your RN version), so I can only make some educated guess.
The non-responsiveness can be caused by the other parts of your application that block your JS thread and prevent the event loop from passing message from the queue to the stack.
To debug this, you can toggle the perfMonitor to see if the JS thread frame rate has dropped to 0. You can also try not to render other elements (e.g. render solely this button in your App.tsx) in your app to see if the issue is gone.
Related
Can someone help me with this Component, i want to make like this, but dont know how this white frames called? Can someone tell me this? And if we press that yellow Touchable Opacity it is showing whole Text, and if we press again it will became smaller!
Thanks in Advance , I am Just new in RN
You can easily create that card with a little bit of CSS.
Below is the sample app which shows you how you can achieve that.
Working Example: Expo Snack
import React, { useState, useEffect } from 'react';
import {
Text,
View,
StyleSheet,
FlatList,
Image,
TouchableOpacity,
} from 'react-native';
import { AntDesign } from '#expo/vector-icons';
import Constants from 'expo-constants';
import { newsFeed } from './news';
export default function App() {
const [news, setNews] = useState(newsFeed);
const showFull = (index) => {
const temp = [...news];
temp[index].toggle = !temp[index].toggle;
setNews(temp);
};
return (
<View style={styles.container}>
<FlatList
data={news}
renderItem={({ item, index }) => (
<View style={styles.card}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.paragraph}>
{item.toggle ? item.desc : `${item.desc.substr(0, 100)}...`}
</Text>
{item.toggle && (
<Image source={{ uri: item.img }} style={styles.img} />
)}
<View style={styles.bottomBar}>
<Text style={styles.date}>4/02/2021</Text>
<TouchableOpacity onPress={() => showFull(index)}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.moreBtn}>
{!item.toggle ? 'More' : 'Less'}
</Text>
<AntDesign
name={item.toggle ? 'up' : 'down'}
size={12}
color="orange"
/>
</View>
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
bottomBar: {
marginVertical: 5,
flexDirection: 'row',
justifyContent: 'space-between',
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
card: {
padding: 10,
backgroundColor: 'white',
marginVertical: 5,
borderRadius: 10,
},
title: {
marginVertical: 5,
fontSize: 18,
fontWeight: 'bold',
},
img: {
flex: 1,
height: 100,
borderRadius: 10,
marginVertical: 5,
},
paragraph: {
fontSize: 14,
},
date: {
fontSize: 12,
color: 'rgba(21,21,21,0.5)',
},
moreBtn: {
fontSize: 12,
color: 'orange',
marginRight: 10,
},
});
actually this card is not a component you can design it using css and if you want to create a component which you can reuse then you can make one component and reuse it as you want and for this card either you can use your own css or a library called native-base which is
like bootstrap but it is used in react-native
you can read about native base here for more information
https://nativebase.io/
and if you want to create card of your own then make a separate file and make a funcional card component in it
and call it wherever you like
import myCustomCard from './card'
and to use it you use like this in your jsx
<myCustomCard />
and if you want to know more about how to pass props and else you can checkout official docs of the react native here
https://reactnative.dev/docs/getting-started
I am trying to make a component in my ReactNative app in which user can give only numbers as input, but my JavaScript reg expression is not working correctly. I used React Native hooks to manage states. I am trying to validate user input for only numbers, but input text field also replacing the numbers with empty string. The code of the component is follwoing;
import React, { useState } from 'react';
import { StyleSheet, Text, View, TextInput, Button, TouchableOpacity } from 'react-native';
import Card from '../components/Card';
import Colors from '../constants/Colors';
import Input from '../components/Input';
const StartGameScreen = props => {
const [enteredValue, setEnteredValue] = useState ('');
const numberInputHandler = inputText => {
setEnteredValue (inputText.replace(/[^0-9]/g, ''));
};
return (
<View style={styles.screen}>
<Text style={styles.title}>Start a New Game</Text>
<Card style={styles.inputContainer}>
<Text>Select a Number</Text>
<Input style={styles.inputText}
blurOnSubmit
auotCaptalize={'none'}
autoCorrect={false}
maxLength={2}
keyboardType={'number-pad'}
onChnageText={numberInputHandler}
value={enteredValue}
/>
<View style={styles.buttonContainer}>
<TouchableOpacity activeOpacity={0.4} style={{backgroundColor: Colors.accent, ...styles.button}}>
<Text style={styles.buttonText}>Reset</Text>
</TouchableOpacity>
<TouchableOpacity activeOpacity={0.4} style={{backgroundColor: Colors.primary, ...styles.button}}>
<Text style={styles.buttonText}>Confirm</Text>
</TouchableOpacity>
</View>
</Card>
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
padding: 10,
alignItems: 'center'
},
button: {
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
height: 35,
width: 80
},
buttonText: {
color: 'white'
},
title: {
fontSize: 20,
marginVertical: 10
},
inputContainer: {
padding: 10,
width: 300,
height: 120,
maxWidth: '80%'
},
inputText: {
width: 35,
textAlign: "center",
},
buttonContainer: {
height: 30,
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
paddingHorizontal: 15,
alignItems: "center"
}
});
export default StartGameScreen;
The code for the input component is following;
import React from 'react';
import { TextInput, StyleSheet} from 'react-native';
const Input = props => {
return (
<TextInput {...props} style={{...styles.input, ...props.style}}/>
);
}
const styles = StyleSheet.create({
input: {
height: 30,
borderBottomWidth: 1,
borderBottomColor: 'grey',
marginVertical: 10
}
});
export default Input;
You've misspelled the prop in your implementation of Input on your StartGameScreen component which is responsible for handling the change.
onChnageText should be onChangeText
The reason your non numbers are "replaced" as well is actually because the change handler isn't mapped to onChangeText due to that typo.
Extra Note:
You've also made another typo in your Input implementation.
auotCaptalize should be autoCapitalize
There are two spelling errors:
auotCaptalize={'none'} should be autoCapitalize={'none'}, and onChnageText={numberInputHandler} should be onChangeText={numberInputHandler}
I would like to do something like this, the only thing I need to know is how to make the gray lines that appear under each component.
By the way I'm using react-navigation.
this is what I want to recreate, I just need to know how to make the intermediate gray line.
Link the Image
My cod:
const DrawerNavigator = createDrawerNavigator({
Example: ScreenExample
},
{
contentComponent: CustomDrawerContentComponent,
drawerWidth: width * 0.63,
contentOptions: {
activeTintColor: blue,
inactiveTintColor: "rgb(105,105,104)",
itemsContainerStyle: {
textAlign: "center"
},
labelStyle: {
fontFamily: "RobotoCondensed-Regular",
fontWeight: "400",
fontSize: 17,
marginLeft: -5
}
},
iconContainerStyle: {
opacity: 1
}
}
const CustomDrawerContentComponent = props => (
<SafeAreaView
style={{ flex: 1, backgroundColor: white }}
forceInset={{ top: "never" }}
>
<SafeAreaView style={{ flex: 0, backgroundColor: "rgb(63,103,149)" }} />
<View
style={{
alignItems: "center",
backgroundColor: "rgb(63,103,149)",
shadowOpacity: 0.3,
shadowOffset: {
height: 5
}
}}
>
<Image
source={require("./src/assets/Icon-Transparente.png")}
style={{ height: 150, width: 150 }}
resizeMode="contain"
/>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</View>
</SafeAreaView>
Just create one common component like this,
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
export default class UnderlinedComponent extends React.Component {
render() {
return (
<View style={{ borderWidth: 1, borderBottomColor: 'grey' }}>
{this.props.children}
</View>
);
}
}
and use it like this,
<UnderlinedComponent>
<Text></Text>
</UnderlinedComponent >
<UnderlinedComponent>
<Button></Button>
</UnderlinedComponent >
this will just create a bottom border, you can customize it as per your need.
and if you don't know how to use contentComponent in a drawer. just see this
I found the answer I was looking for by researching at: https: //reactnavigation.org/docs/en/drawer-navigator.html#contentoptions-for-draweritems
I found that inside the drawer there is a property called itemStyle and use it as follows
itemStyle: {
borderBottomWidth: 0.5,
borderBottomColor: gray
}
with this adding it to contentOptions I could create the lines below the items :)
In React Native, I have this component:
<TouchableHighlight onPress={this.selectItem}>
<Text
style={this.getTextIndexStyle()}>
{someText}
</Text>
</TouchableHighlight>
This Text component calls this method to get its styling:
getTextIndexStyle() {
return {
position: 'absolute',
opacity: 0.75,
backgroundColor: this.getTextBoxColor(),
textAlign: 'center',
color: '#ffffff',
fontSize: 20,
fontWeight: 'bold'
};
}
Which in turn calls this method to get its color.
getTextBoxColor() {
if(this.state.highlighted) {
return Constants.HIGHLIGHTED_TEXT_BOX_COLOR;
}
return Constants.UNHIGHLIGHTED_TEXT_BOX_COLOR;
}
Also, when the user clicks the TouchableHighlight, he or she triggers this:
selectItem() {
this.setState({highlighted: true});
}
My problem is that if I click on the TouchableHighlight, the Text component doesn't change its colour.
I'm not sure if this.state is not updated or if it is updated but for some strange reason this.getTextBoxColor() is not called.
Any idea how to make the colour update?
You have an error in the JSX of the onPress of your TouchableHighlight, you can fix it by changing to:
<TouchableHighlight onPress={() => this.selectItem}>
You should also create a StyleSheet and pass the color you wish to it during rendering
const style = (backgroundColor) => (
StyleSheet.create({
textStyle: {
position: 'absolute',
opacity: 0.75,
backgroundColor,
textAlign: 'center',
color: '#ffffff',
fontSize: 20,
fontWeight: 'bold'
})
);
then, on you render method:
render(){
const styles=style(getTextBoxColor())
return(
...
)
}
and on your Text:
<Text
style={styles.textStyle}>
{someText}
</Text>
EDIT: ({backgroundColor}) => (backgroundColor)
I have a disappearing header which I want to bring back into the view on a single tap anywhere on the screen. But if I am wrapping the entire <View> inside a <TouchableX> component the PanResponder stops working. Is there a hack around this?
You do not need to warp it with Touchable component.
Add next props to root View.
onResponderGrant - make View handle touch
onStartShouldSetResponder - make View handle start
To elaborate #Nicholas Chong advice, here is the example that works for me fine. You can use onTouchStart and onTouchEnd handlers on any View via props:
<View
onTouchStart={() => doSomething()}
style={{ width: '100%', height: '100%' }}
/>
More information
onResponderGrant not working for me, and I use onTouchEnd to trigger when tap the screen, this will work
This would be an example of a implementation with a onResponderGrant
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component<{}> {
constructor() {
super();
this.startTouch = this.startTouch.bind(this);
this.stopTouch = this.stopTouch.bind(this);
this.onTouchE = this.onTouchE.bind(this);
}
startTouch() {
console.debug("You start so don't stop!??");
}
stopTouch() {
console.debug("Why you stop??");
}
onTouchE() {
console.debug("Touchable Opacity is working!!");
}
render() {
return (
<View style={styles.container}
onResponderGrant = { () => this.startTouch() }
onResponderRelease = { () => this.stopTouch() }
onStartShouldSetResponder = { (e) => {return true} }
>
<TouchableOpacity
onPress = { () => this.onTouchE() }
>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
</TouchableOpacity>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'cornflowerblue',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
I have included an example of using onResponderGrant and onStartShouldSetResponder inside of a View component.
(Thanks to your previously written answer, #Mr Br)
Definitions
import { Modal, Text, View } from "react-native";
import { useState } from "react";
const [visible, setVisible] = useState(false);
const dismissFunction = () => setVisible(false);
Presentation
<Modal visible={visible} transparent style={{ alignItems: "center", height: "100%", }} >
<View onResponderGrant={dismissFunction} onStartShouldSetResponder={dismissFunction} style={{ flex: 1, backgroundColor: "#1c1c1c75", flexDirection: "column", justifyContent: "flex-end", alignItems: "center" }} >
<View style={{ backgroundColor: "#1E2124", borderRadius: 30, justifyContent: "center", alignItems: "center", height: "30%", shadowColor: "#ffffff10", shadowOpacity: 10, shadowOffset: { width: 0, height: -5 }, width: "101%" }}>
<Text style={{ textAlign: "center", color: "#ffffff", fontSize: 24, marginLeft: "10%", marginRight: "10%", marginBottom: "10%", marginTop: "5%" }}>The message of your modal!</Text>
</View>
</View>
</Modal>
Don't forget to run setVisible(true) somewhere to get the modal to show!