I have 5 button "35,17,11,8,5" when I press a button I want to add the button's value to a list, so I did that.
import React, { useState } from "react";
import { StyleSheet, Text, View, Pressable, TextInput } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
function AddtoArray(array,value){
console.log('a', 'a');
const [arrayToChange, setArrayToChange] = useState(array);
console.log('a1', 'a1');
const [valueToAdd, setValueToAdd] = useState(value);
console.log('a2', 'a2');
const newArray = () => {
setArrayToChange([...arrayToChange, value]);
};
console.log('b',newArray, 'b');
return newArray;
};
function RouletteExercice1 ({ navigation }){
const [multiplyArray, setMultiplyArray] = useState([]);
return(
<View>
<Pressable onPress={() => {setMultiplyArray(AddtoArray(multiplyArray,'35'))}}>
<Text>35</Text>
</Pressable>
<Pressable onPress={() => {setMultiplyArray(AddtoArray(multiplyArray,'17'))}}>
<Text>17</Text>
</Pressable>
<Pressable onPress={() => {setMultiplyArray(AddtoArray(multiplyArray,'11'))}}>
<Text>11</Text>
</Pressable>
<Pressable onPress={() => {setMultiplyArray(AddtoArray(multiplyArray,'8'))}}>
<Text>8</Text>
</Pressable>
<Pressable onPress={() => {setMultiplyArray(AddtoArray(multiplyArray,'5'))}}>
<Text>5</Text>
</Pressable>
</View>
)
}
But when I press a button the app say "invalic hook call" and on the console all i have is "a a".
Can someone tell me what is the problem ? please
Your AddtoArray function is outside of your functional component, RouletteExercice1.
When you call useState, you're adding state to the functional component that you're calling useState from. You must call useState from the functional component.
That said, you don't need state for arrayToChange or valueToAdd. You're only changing the one array, and you're passing the value to the function.
import React, { useState } from "react";
import { StyleSheet, Text, View, Pressable, TextInput } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
function RouletteExercice1 ({ navigation }){
const [multiplyArray, setMultiplyArray] = useState([]);
function AddtoArray(value){
setMultiplyArray((prev) => [...prev, value])
}
return(
<View>
<Pressable onPress={() => {AddtoArray('35')}}>
<Text>35</Text>
</Pressable>
<Pressable onPress={() => {AddtoArray('17')}}>
<Text>17</Text>
</Pressable>
<Pressable onPress={() => {AddtoArray('11')}}>
<Text>11</Text>
</Pressable>
<Pressable onPress={() => {AddtoArray('8')}}>
<Text>8</Text>
</Pressable>
<Pressable onPress={() => {AddtoArray('5')}}>
<Text>5</Text>
</Pressable>
</View>
)
}
Related
I have a component called Header that look like this:
import React from 'react'
import {StyleSheet, TouchableOpacity, View, StyleProp, ViewStyle} from 'react-native'
import {Text} from '..'
import Icon from 'react-native-vector-icons/MaterialIcons'
import {theme} from '#app/presentations/utils/styles'
import {useNavigation} from '#react-navigation/core'
interface IHeaderProps {
title: string
headerRight?: () => JSX.Element | false | undefined
onGoBack?: () => void
hideBackButton?: boolean
style?: StyleProp<ViewStyle>
}
const Header: React.FC<IHeaderProps> = props => {
const navigation = useNavigation()
const goBack = () => {
props.onGoBack ? props.onGoBack : navigation.goBack()
}
return (
<View style={[styles.container, props.style]}>
<View style={styles.leftContent}>
{props?.hideBackButton ? null : (
<TouchableOpacity onPress={goBack} testID="headerBackButton">
<Icon name={'chevron-left'} size={22} color={theme.colors.black} />
</TouchableOpacity>
)}
</View>
<View style={{flex: 1, flexGrow: 10, alignItems: 'center'}}>
<Text maxLines={2} style={{paddingHorizontal: 8, textAlign: 'center'}} type="semibold">
{props.title}
</Text>
</View>
<View style={styles.rightContent}>{props.headerRight && props.headerRight()}</View>
</View>
)
}
export default Header
Focus on TouchableOpacity, I want to fire the onPress of it using testId, but looks like it won't fire.
it('Should have correct behavior', () => {
const goBackFn = jest.fn()
const props: IHeaderProps = {
title: 'My Header',
onGoBack: goBackFn,
}
const {component, getByTestId, queryAllByText} = renderComponent(props)
expect(component).toMatchSnapshot()
expect(queryAllByText('My Header').length).toBe(1)
expect(getByTestId('headerBackButton')).toBeTruthy()
fireEvent.press(getByTestId('headerBackButton'))
expect(goBackFn).toBeCalled()
})
The error message was like this
means that my goBack function never executed. I wondering why.
Then I check the snapshots of my Header component, it is not show TouchableOpacity but it shows View with onClick function on it
<View
accessible={true}
collapsable={false}
focusable={true}
nativeID="animatedComponent"
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
testID="headerBackButton"
>
My question is how do I execute onPress on TouchableOpacity ?
I fixed this. At least there is two problem from my implementation.
On the Header component, I forgot to add parenthesis () on props.onGoBack function. It should be props.onGoBack() not props.onGoBack
I need to add await waitFor(() => { ...wait for my getTestById to be truthy })
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>
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;
I got some error when i have used goBack(null) method in functional component in react navigation
function Header({ titleText, navigation}) {
return (
<Appbar.Header style={styles.headerContainer}>
<Appbar.BackAction style={styles.backButton} onPress={() => navigation.goBack(null)} >
<Text style={styles.back}></Text>
</Appbar.BackAction>
<View style={styles.container}>
<Title style={styles.title}>{titleText}</Title>
</View>
</Appbar.Header>
)}
Try with useNavigation hook from #react-navigation/native
import * as React from 'react';
import { Text } from 'react-native';
import { useNavigation } from '#react-navigation/native';
function MyText() {
const navigation = useNavigation();
return <Text onPress={() => navigation.goBack()}>Go Back</Text>;
}
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.