Expo / TouchableOpacity onPress() not responding - react-native

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>

Related

Functional components cannot be given refs with react-native-rich-editor on Expo

I am trying to use this package :
https://www.npmjs.com/package/react-native-pell-rich-editor
And I have the following code :
import { useState, useRef } from "react";
import { RFPercentage } from "react-native-responsive-fontsize";
import BottomSheet from "#gorhom/bottom-sheet";
import {
StyleSheet,
View,
Text,
Platform,
KeyboardAvoidingView,
SafeAreaView,
ScrollView,
} from "react-native";
import {
actions,
RichEditor,
RichToolbar,
} from "react-native-pell-rich-editor";
export default function Publish() {
const postSheetRef = useRef(null);
const richText = useRef();
const snapPoints = ["90%"];
};
return (
<>
<View style={styles.container}>
<View style={styles.publishHeader}>
<Text style={styles.titleHeader}>Publier un post</Text>
</View>
<BottomSheet
ref={postSheetRef}
snapPoints={snapPoints}
handleIndicatorStyle={{ display: "none" }}
>
<View style={styles.main}>
<SafeAreaView>
<ScrollView>
<RichEditor
ref={richText}
onChange={(descriptionText) => {
console.log("descriptionText:", descriptionText);
}}
/>
</ScrollView>
<RichToolbar
editor={richText}
actions={[
actions.setBold,
actions.setItalic,
actions.setUnderline,
actions.heading1,
]}
iconMap={{
[actions.heading1]: ({ tintColor }) => (
<Text style={[{ color: tintColor }]}>H1</Text>
),
}}
/>
</SafeAreaView>
</View>
</BottomSheet>
</View>
</>
);
}
I get this error :
Functional components cannot be given refs
It concerns the Rich Editor component.
But I just followed the documentation, so I can't understand why.
I use ref with the Bottom sheet component and it works perfectly.
I am working with Expo.
How can I solve this ? This is the only package I have found that is compatible with Expo so I need to make it work ^^.
<RichEditor
ref={(r)=>{richText.current = r}}
onChange={(descriptionText) => {
console.log("descriptionText:", descriptionText);
}}
/>

Function components cannot be given refs with react-native-rich-editor on Expo

I am trying to use this package :
https://www.npmjs.com/package/react-native-pell-rich-editor
And I have the following code :
import { useState, useRef } from "react";
import { RFPercentage } from "react-native-responsive-fontsize";
import BottomSheet from "#gorhom/bottom-sheet";
import {
StyleSheet,
View,
Text,
SafeAreaView,
ScrollView,
} from "react-native";
import {
actions,
RichEditor,
RichToolbar,
} from "react-native-pell-rich-editor";
export default function Publish() {
const postSheetRef = useRef(null);
const richText = useRef();
const snapPoints = ["90%"];
};
return (
<>
<View style={styles.container}>
<View style={styles.publishHeader}>
<Text style={styles.titleHeader}>Publier un post</Text>
</View>
<BottomSheet
ref={postSheetRef}
snapPoints={snapPoints}
handleIndicatorStyle={{ display: "none" }}
>
<View style={styles.main}>
<SafeAreaView>
<ScrollView>
<RichEditor
ref={richText}
onChange={(descriptionText) => {
console.log("descriptionText:", descriptionText);
}}
/>
</ScrollView>
<RichToolbar
editor={richText}
actions={[
actions.setBold,
actions.setItalic,
actions.setUnderline,
actions.heading1,
]}
iconMap={{
[actions.heading1]: ({ tintColor }) => (
<Text style={[{ color: tintColor }]}>H1</Text>
),
}}
/>
</SafeAreaView>
</View>
</BottomSheet>
</View>
</>
);
}
I get this error :
Function components cannot be given refs
It concerns the Rich Editor component.
But I just followed the documentation, so I can't understand why.
According to the github repo of the package, RichEditor seems to be a class component ...
Anyway, the documentation tells me to use Ref.
I tried this :
<RichEditor
ref={(r)=>{richText.current = r}}
onChange={(descriptionText) => {
console.log("descriptionText:", descriptionText);
}}
/>
But it did not help.
I am working with Expo.
How can I solve this ? This is the only package I have found that is compatible with Expo so I need to make it work ^^.

Get the childrens of an element in react native using useRef

I am trying to understand how to use useRef in React Native and get the children of a View element, but I couldn't figure out to achieve it.
I am trying to use the .focus method in the TextInput component on press on the TouchableOpacity
Declaration:
const input = useRef(null);
TextInputComponent:
<View ref={input}>
<Tex>Email</Text>
<TextInput placeholder=""/>
</View>
Element:
<TouchableOpacity onPress={() => {}}>
<TextInputComponent />
</TouchableOpacity>
i tried input.current.children, but it returns undefined.
This is a working example of how to achieve what you want using on a basic expo init project on TypeScript:
App.tsx
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, TextInput, TouchableOpacity} from "react-native";
import { useRef, forwardRef} from "react";
const TextInputComponent = forwardRef<TextInput>((props, ref) => {
return (
<View>
<Text>Email</Text>
<TextInput ref={ref} placeholder="Some placeholder" />
</View>
);
});
export default function App() {
const input = useRef<TextInput>(null)
return (
<View style={styles.container}>
<Text>Open up App.tsx to start working on your app!</Text>
<StatusBar style="auto" />
<TouchableOpacity onPress={() => {
input.current?.focus();
}}>
<TextInputComponent ref={input} />
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
In this case it is more practical to use a forwardRef so you don't have to loop through the children of the View component to pass a ref from the component (App in this case) that is using TextInputComponent.

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;

Reusable Button with Image

So i'm new to react native and javascript, and i want to make a reusable button with image and i found this code
import React from 'react';
import { Image, TouchableOpacity } from 'react-native';
const ImgButtons = ({ onPress, img }) => {
return (
<TouchableOpacity onPress={onPress}>
<Image
source={require(img)}
/>
</TouchableOpacity>
);
};
export { ImgButtons };
and i call the component
<View style={styles.innerContainer}>
<ImgButtons
img={require('../assets/btn-reg-1.jpg')}/>
</View>
i got an error say Error: component/ImgButtons.js:Invalid call at line 9: require(img)
can somebody help me? Thanks :)
In you custom component I edited Image source check below:
import React from 'react';
import { Image, TouchableOpacity } from 'react-native';
const ImgButtons = ({ onPress, img }) => {
return (
<TouchableOpacity onPress={onPress}>
<Image
source={img}
/>
</TouchableOpacity>
);
};
export { ImgButtons };
Then you have to pass some method onPress
<View style={styles.innerContainer}>
<ImgButtons
img={require('../assets/btn-reg-1.jpg')}
onPress={()=>console.log('Action')}
/>
</View>