TouchableOpacity is not detecting instant touch - javascript

I used TouchableOpacity to make a custom button component but its opacity works after some delay when I touch the button using expo client app.
The code of my component is following:
import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const CustomButton = ({ label, btnStyle, textStyle, btnType }) => {
const checkBtnType = type => {
if (type === "small") return styles.btnSmall;
if (type === "medium") return styles.btnMedium;
if (type === "large") return styles.btnLarge;
}
return (
<TouchableOpacity activeOpacity={0.4}
style={{ ...styles.btn, ...checkBtnType(btnType), ...btnStyle }}>
<Text style={{ ...styles.text, ...textStyle }}>{label}</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
btn: {
alignItems: "center",
justifyContent: "center",
borderRadius: 25,
},
btnSmall: {
height: 34,
width: 140,
},
btnMedium: {
height: 50,
width: 162,
},
btnLarge: {
height: 50,
width: 347,
},
text: {
fontSize: 14,
fontFamily: 'SFPro-Regular',
fontWeight: "bold",
}
});
export default CustomButton;
I am using my component inside a screen. The for the screen is following:
import React from 'react';
import { SafeAreaView, StyleSheet, View, StatusBar } from 'react-native';
import CustomButton from '../components/customButton';
import Heading from '../components/heading';
import Colors from '../constants/Colors';
const SignUp = (props) => {
return (
<SafeAreaView style={styles.container}>
<StatusBar backgroundColor="#ffffff" barStyle="dark-content" />
<Heading label="Sign up" style={styles.topHeading} />
<Heading label="Sign up with" style={styles.subHeading} />
<CustomButton label="Email" btnType="large" style={{ backgroundColor: Colors.primary }} />
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
paddingHorizontal: 10,
},
topHeading: {
fontSize: 24,
paddingTop: 42,
paddingBottom: 180,
},
subHeading: {
fontSize: 14,
alignSelf: "flex-start",
paddingVertical: 20,
}
});
export default SignUp;
I have also used the same component in another project and did not face any issue.

TouchableOpacity wraps its children with Animated.View. It seems your styles affected to animated styles. Are inside { ...styles.btn, ...checkBtnType(btnType), ...btnStyle } some opacity props ?

Related

is there a way to remove title on each screens in expo?

i am a beginner in react-native, i follow tutorials on youtube to make projects. i am trying to make an expo ui-app, but each screens has a title on the top like this:
There is the word Explore above the screen, and each other screens has the corresponding title above it aswell. Is there a way to remove this? because i followed tutorials from youtube but they didnt have this title.
Here is the Explore.js file:
import { StyleSheet, Text, View, SafeAreaView, TextInput, Platform, StatusBar } from 'react-native';
import React, { Component } from 'react';
import { Ionicons } from '#expo/vector-icons';
class Explore extends Component {
componentWillMount() {
this.startHeaderHeight = 80
if(Platform.OS == 'android')
{
this.startHeaderHeight = 100 + StatusBar.currentHeight
}
}
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<View style={{ height: this.startHeaderHeight, backgroundColor: 'white', borderBottomWidth: 1, borderBottomColor: '#dddddd' }}>
<View style={{flexDirection: 'row', padding: 10, backgroundColor: 'white', marginHorizontal: 20, shadowOffset:{width:0,height:0}, shadowColor: 'black', shadowOpacity: 0.2, elevation: 1, marginTop: Platform.OS == 'android' ? 30 : 20 }}>
<Ionicons name="ios-search" size={20} color="black" />
<TextInput
underlineColorAndroid="transparent"
placeholder='Try Indonesia'
placeholderTextColor="grey"
style={{ flex: 1, fontWeight: '700', backgroundColor: 'white', marginLeft: 10 }}
/>
</View>
</View>
</View>
</SafeAreaView>
);
}
}
export default Explore;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
and here is my app.js file:
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { Ionicons } from '#expo/vector-icons';
import { FontAwesome5 } from '#expo/vector-icons';
import Explore from './screens/Explore';
import Saved from './screens/Saved';
import Trips from './screens/Trips';
import Inbox from './screens/Inbox';
const Tab = createBottomTabNavigator();
export default function BottomTabs() {
return (
<NavigationContainer>
<..... CODE OF THE BOTTOM TAB NAVIGATOR IN HERE .....>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
David Scholz's solution is good for individual screens. If you want to disable the header on all child screens of a navigator, you can use
screenOptions={{ headerShown: false }}
as a prop on the Tab.Navigator, or any top-level navigator.
You could hide the header using the options={{headerShown: false}} prop as follows.
const Tab = createBottomTabNavigator();
export default function BottomTabs() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Test" options={{
headerShown: false
}}/>
</Tab.Navigator>
</NavigationContainer>
);
}

tabBarOptions not applied to project (React Native)

I am creating a small app that has a to-do list and a calendar. At the bottom is a bottom tab navigator. Everything works and is functional, however, when I try to add style: {} inside tabBarOptions it isn't being applied. Changing activeTintColor, inactiveTintColor and labelStyle works just fine.
I tried to create a stylesheet and replace everything inside tabBarOptions, but that didn't work. My main goal is to simply create a slightly larger bar along the bottom of the screen. I don't even want a crazy custom navigation bar, just slightly larger so I can make the items inside a little bigger.
MainContainer Class:
import React from 'react';
import {StyleSheet} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons'
//screens
import Calendar from './screens/Calendar';
import ToDoList from './screens/ToDoList';
// Screen names
const calendarName = 'Calendar';
const ToDoListName = 'To Do List';
const Tab = createBottomTabNavigator();
export default function MainContainer() {
return (
<NavigationContainer>
<Tab.Navigator
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'black',
labelStyle: {paddingBottom: 10, fontSize: 10},
style: {padding: 10, height: 70},
}}
initialRouteName={ToDoListName}
screenOptions={({route}) => ({
tabBarIcon: ({focused, color, size}) => {
let iconName;
let rn = route.name;
if (rn === ToDoListName) {
iconName = focused ? 'list' : 'list-outline'; //icons in package. Change later.
} else if (rn === calendarName) {
iconName = focused ? 'calendar' : 'calendar-outline'
}
return <Ionicons name={iconName} size={size} color={color}/>
},
})}>
<Tab.Screen name={ToDoListName} component={ToDoList}/>
<Tab.Screen name={calendarName} component={Calendar}/>
</Tab.Navigator>
</NavigationContainer>
)
}
For reference here is my ToDoList class
import { KeyboardAvoidingView, StyleSheet, Text, View, TextInput, TouchableOpacity, Platform, Keyboard } from 'react-native';
import Task from '../../components/Task';
import React, { useState } from 'react';
import { ScrollView } from 'react-native-web';
export default function ToDoList() {
const [task, setTask] = useState();
const [taskItems, setTaskItems] = useState([]);
const handleAddTask = () => {
Keyboard.dismiss();
setTaskItems([...taskItems, task])
setTask(null);
}
const completeTask = (index) => {
let itemsCopy = [...taskItems];
itemsCopy.splice(index, 1);
setTaskItems(itemsCopy)
}
return (
<View style={styles.container}>
{/* Scroll View when list gets longer than page */}
<ScrollView contentContainerStyle={{
flexGrow: 1
}} keyboardShouldPersistTaps='handled'>
{/*Today's Tasks */}
<View style={styles.tasksWrapper}>
<Text style={styles.sectionTitle}>Today's Tasks</Text>
<View style={styles.items}>
{/* This is where the tasks will go*/}
{
taskItems.map((item, index) => {
return (
<TouchableOpacity key={index} onPress={() => completeTask(index)}>
<Task text={item} />
</TouchableOpacity>
)
})
}
</View>
</View>
</ScrollView>
{/* Write a task section */}
{/* Uses a keyboard avoiding view which ensures the keyboard does not cover the items on screen */}
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.writeTaskWrapper}>
<TextInput style={styles.input} placeholder={'Write a task'} value={task} onChangeText={text => setTask(text)} />
<TouchableOpacity onPress={() => handleAddTask()}>
<View style={styles.addWrapper}>
<Text style={styles.addText}>+</Text>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#E8EAED',
},
tasksWrapper: {
paddingTop: 20,
paddingHorizontal: 20,
},
sectionTitle: {
fontSize: 24,
fontWeight: 'bold',
},
items: {
marginTop: 30,
},
writeTaskWrapper: {
position: 'absolute',
bottom: 20,
paddingLeft: 10,
paddingRight: 10,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
input: {
paddingVertical: 15,
width: 250,
paddingHorizontal: 15,
backgroundColor: '#FFF',
borderRadius: 60,
borderColor: '#C0C0C0',
borderWidth: 1,
},
addWrapper: {
width: 60,
height: 60,
backgroundColor: '#FFF',
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
borderColor: '#C0C0C0',
borderWidth: 1,
},
addText: {
},
});
And my Calendar class
import * as React from 'react';
import { View, Text } from 'react-native';
export default function Calendar(){
return(
<View>
<Text>Calendar Will go here</Text>
</View>
)
}
I made a Task component for the ToDoList. Not sure if you need it to solve this but I'll paste it here anyway.
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { TouchableOpacity } from 'react-native-web';
const Task = (props) => {
return (
<View style={styles.item}>
<View style={styles.itemLeft}>
<View style={styles.square}></View>
<Text style={styles.itemText}>{props.text}</Text>
</View>
<View style={styles.circular}></View>
</View>
)
}
const styles = StyleSheet.create({
item: {
backgroundColor: '#FFF',
padding: 15,
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
},
itemLeft: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
},
square: {
width: 24,
height: 24,
backgroundColor: '#55BCF6',
opacity: .4,
borderRadius: 5,
marginRight: 15,
},
itemText: {
maxWidth: '80%',
},
circular: {
width: 12,
height: 12,
borderColor: '#55BCF6',
borderWidth: 2,
borderRadius: 5
},
});
export default Task;
It sounds like you are looking for the tabBarStyle property. You should be able to rename style (which is not a supported prop of the tab navigator) to tabBarStyle.
Here's the spot in the docs that mentions this. https://reactnavigation.org/docs/bottom-tab-navigator#tabbarstyle
What I ended up doing to solve this was to put the styling inside the screenOptions. I didn't want to do this because I wanted to separate the styling from the logic, but it solved the problem for me. See code below:
export default function MainContainer() {
return (
<NavigationContainer>
<Tab.Navigator
initialRouteName={ToDoListName}
screenOptions={({route}) => ({
tabBarIcon: ({focused, color, size}) => {
let iconName;
let rn = route.name;
if (rn === ToDoListName) {
iconName = focused ? 'list' : 'list-outline'; //icons in package. Change later.
} else if (rn === calendarName) {
iconName = focused ? 'calendar' : 'calendar-outline'
}
return <Ionicons name={iconName} size={size} color={color}/>
},
activeTintColor: 'tomato',
inactiveTintColor: 'black',
tabBarShowLabel: false,
tabBarStyle: {padding: 10, height: 100, backgroundColor: 'black'},
})}>
<Tab.Screen name={ToDoListName} component={ToDoList}/>
<Tab.Screen name={calendarName} component={Calendar}/>
</Tab.Navigator>
</NavigationContainer>
)
}

React Navigation saying nothing was returned from render

I have React navigation setup to return my component, everything so far seems to be setup properly from what I've read and watched, when I load up the app through expo I get "Invariant Violation: _default(...): Nothing was returned from render." I'm not sure if there's something wrong with my Navigator itself or how I'm calling my Navigator maybe? Not sure exactly how it knows to call that specific component in the HomeStack.Navigator, I would figure it needed some sort of like route to call to load that specific component by it's name? Might be missing a whole file, not sure.
Navigation file
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import Home from "../Home";
const HomeStack = createStackNavigator();
const HomeStackScreen = () => {
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={Home} />
</HomeStack.Navigator>;
};
export default () => {
<NavigationContainer>
<HomeStackScreen />
</NavigationContainer>;
};
App.js file
import React from "react";
import Navigation from "./config/navigation";
export default () => <Navigation />;
Home component file
import React from "react";
import { StyleSheet, Text, View, ScrollView } from "react-native";
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
bannerText: "PNW Plants",
};
}
render() {
return (
<View style={styles.container}>
<View style={styles.banner}>
<Text style={styles.bannerText}>{this.state.bannerText}</Text>
</View>
<Text
style={{
color: "darkgreen",
marginTop: 40,
fontSize: 22,
textDecorationLine: "underline",
textDecorationColor: "lightgrey",
}}
>
Discovered Plants
</Text>
<ScrollView
style={styles.grid}
contentContainerStyle={{ flexDirection: "row", flexWrap: "wrap" }}
>
<Text style={styles.gridUnit1}></Text>
<Text style={styles.gridUnit}></Text>
<Text style={styles.gridUnit}></Text>
<Text style={styles.gridUnit}></Text>
<Text style={styles.gridUnit1}></Text>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
alignItems: "center",
overflow: "scroll",
},
banner: {
backgroundColor: "darkgreen",
height: 55,
width: "100%",
justifyContent: "center",
alignItems: "center",
},
bannerText: {
color: "white",
fontSize: 30,
fontWeight: "bold",
},
gridBanner: {
fontSize: 26,
marginTop: 40,
color: "darkgreen",
},
grid: {
display: "flex",
padding: 10,
width: "90%",
borderTopWidth: 1,
borderBottomWidth: 1,
height: "60%",
borderStyle: "solid",
borderColor: "lightgrey",
marginTop: 40,
overflow: "hidden",
},
gridUnit: {
backgroundColor: "lightgrey",
height: 80,
width: 80,
margin: 10,
overflow: "scroll",
},
gridUnit1: {
backgroundColor: "orange",
height: 80,
width: 80,
margin: 10,
},
});
Add return if you are using curly braces in an arrow function
const HomeStackScreen = () => {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={Home} />
</HomeStack.Navigator>
)
};
or simply do like this
const HomeStackScreen = () => (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={Home} />
</HomeStack.Navigator>
)
};
In your code, HomeStackScreen is returning undefined, that's why you are getting the error.
Also, modify
export default () => (
<NavigationContainer>
<HomeStackScreen />
</NavigationContainer>;
})

User input validation is not working correctly

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}

Invariant Violation: Element type is invalid: React Native

I started to learning react native a 4-5 days ago and now I am building a login screen in React Native. But facing this issue, I am trying to figure it out but unfortunately, I couldn't do so. Can guys please help me? I am attaching my code and screenshot Here.Error Screenshot
App.js
import React, { Component} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Login from './src/screens/Login';
export default class App extends Component {
render() {
return (
<Login />
);
}
}
Here is the Login screen code
Login.js
import React, { Component} from 'react';
import { StyleSheet, TextInput, View, Image, StatusBar, Dimensions } from 'react-native';
import { LinearGradient } from 'expo';
import EStyleSheet from 'react-native-extended-stylesheet';
import { Button } from '../components/Button';
import { Ionicons } from '#expo/vector-icons';
const {width: WIDTH} = Dimensions.get('window')
EStyleSheet.build();
export default class Login extends Component {
render() {
return (
<LinearGradient
colors={['#38E870', '#2BB256']}
style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.logocontainer}>
<Image source={require('../images/Devastic.png/')} />
</View>
<View style={styles.formContainer}>
<View style={styles.inputcontainer}>
<Ionicons name="ios-person-outline" size={36} color="#747475"
style={styles.inputemail}/>
<TextInput
placeholder={'Enter Your Email'}
underlineColorAndroid={'transparent'}
placeholderTextColor="#dfe6e9"
style={styles.input}
/>
<Ionicons name="ios-unlock-outline" size={34} color="#747475"
style={styles.inputpass}/>
<TextInput
placeholder={'Enter Your Password'}
secureTextEntry={true}
underlineColorAndroid={'transparent'}
placeholderTextColor="#dfe6e9"
style={styles.input}
/>
<Button
text="Log In"
onPress={() => console.log ("Pressed")}
/>
</View>
</View>
</LinearGradient>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
},
logocontainer: {
paddingTop: 50,
},
formContainer: {
backgroundColor: '#FFF',
marginTop: 180,
width: 360,
height: 340,
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.6,
shadowRadius: 6,
elevation: 8,
},
inputcontainer: {
marginTop: 30,
},
inputemail: {
position: 'absolute',
left: 18,
top: 13,
},
inputpass: {
position: 'absolute',
left: 18,
top: 77,
},
input: {
width: WIDTH -50 ,
height: 44,
padding: 10,
paddingLeft: 40,
marginVertical: 10,
marginHorizontal: 10,
borderWidth: 1,
borderRadius: 20,
borderColor: 'black',
marginBottom: 10,
}
});
here is the Button.js File code
import React from 'react';
import { View, TouchableHighlight, TouchableNativeFeedback, Text, Platform } from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
const styles = EStyleSheet.create({
$buttonColor: '#38E870',
$buttonTextColor: '#ffffff',
$buttonUnderlayColor: '#2BB256',
button: {
backgroundColor: '$buttonColor',
paddingVertical: 10,
paddingHorizontal: 30,
marginHorizontal: 12,
borderRadius: 40,
marginTop: 20,
},
text: {
color: '$buttonTextColor',
fontSize: 18,
textAlign: 'center',
fontWeight: 'bold',
},
});
export const Button = ({ text, onPress }) => {
if (Platform.OS === 'ios') {
return (
<TouchableHighlight
onPress={onPress}
style={styles.button}
underlayColor={styles.$buttonUnderlayColor}
>
<Text style={styles.text}>{text}</Text>
</TouchableHighlight>
);
}
return (
<TouchableNativeFeedback
onPress={onPress}
background={TouchableNativeFeedback.Ripple(styles.$buttonUnderlayColor)}
>
<View style={styles.button}>
<Text style={styles.text}>{text}</Text>
</View>
</TouchableNativeFeedback>
);
};
In your Login.js file, you are importing Button as object.
Change as following:
From
import { Button } from '../components/Button';
To
import Button from '../components/Button';
For more information, please have a look : Uncaught Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function but got: object
Hope this will help !
I think the issue because the way you have exported the Button component.
export foo;
import {foo} from 'blah';
export default foo;
import foo from 'blah';
solution to your problem
Replace this
export const Button = ({ text, onPress }) =>
with this
export default const Button = ({ text, onPress }) =>
for more detail check this more detail

Categories

Resources