Navigation not working on custom button react native - reactjs

hope someone would help me with this problem. I have create my own buttons and when I`m calling them as a component in a screen onPress navigation is not working, only in the Button Component from react native. This is my code:
Custom Button:
export const MediumButton = ({ title }) => {
return (
<TouchableOpacity style={styles.mediumButton}>
<Text style={styles.buttonText}>{title}</Text>
</TouchableOpacity>
);
};
And this is the code of screen that I`m calling the MediumButton:
import { MediumButton } from "../../components/Button/Button";
export default function Home({ navigation }) {
return (
<View style={global.container}>
<View style={styles.container}>
<Text style={styles.titleText}>Miresevini ne Hajde App</Text>
<MediumButton
title="Kycu"
onPress={() => navigation.navigate("Register")}
/>
<MediumButton
title="Regjistrohu"
onPress={() => navigation.navigate("Login")}
/>
</View>
</View>
);
}

You have to use the onPress prop that you are passing like below
export const MediumButton = ({ title,onPress }) => {
return (
<TouchableOpacity style={styles.mediumButton} onPress={onPress}>
<Text style={styles.buttonText}>{title}</Text>
</TouchableOpacity>
);
};

Try to pass the onPress handler to TouchableOpacity:
export const MediumButton = ({ title, onPress }) => {
return (
<TouchableOpacity style={styles.mediumButton} onPress={onPress}>
<Text style={styles.buttonText}>{title}</Text>
</TouchableOpacity>
);
};

Related

Invalid hook call React Native FlatList Navigation

I'm making a notes app in React Native and trying to make it so I can click on a note in a FlatList to edit it. I'm using react-router-native for this. I get an Error when clicking on any FlatList item. I know that this error has been asked on stack overflow before but the answers are all for class components, whereas I'm using functional components.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
import { FlatList, Pressable, StyleSheet, View } from "react-native"
import { useNavigate } from "react-router-native"
import theme from "../theme"
import Text from "./Text"
const styles = StyleSheet.create({
separator: {
height: 10,
backgroundColor: theme.colors.background,
},
item: {
padding: 8,
backgroundColor: "white",
},
})
const ItemSeparator = () => <View style={styles.separator} />
const renderItem = ({ item }) => (
<View style={styles.item}>
<Pressable onPress={() => useNavigate(`/${item.id}`)}>
<Text fontWeight="bold" fontSize="subheading">
{item.title}
</Text>
<Text>{item.body}</Text>
</Pressable>
</View>
)
const NoteList = ({ notes }) => {
return (
<FlatList
data={notes}
ItemSeparatorComponent={ItemSeparator}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
)
}
useNavigate is a React hook and can only be called by a React function component or other custom React hook. It cannot be called in nested functions/callbacks.
Move the useNavigate hook call to the NoteList component and refactor the renderItem callback to curry a passed navigate function.
const ItemSeparator = () => <View style={styles.separator} />;
const renderItem = (navigate) => ({ item }) => (
<View style={styles.item}>
<Pressable onPress={() => navigate(`/${item.id}`)}>
<Text fontWeight="bold" fontSize="subheading">
{item.title}
</Text>
<Text>{item.body}</Text>
</Pressable>
</View>
);
const NoteList = ({ notes }) => {
const navigate = useNavigate(); // <-- hook called in React function
return (
<FlatList
data={notes}
ItemSeparatorComponent={ItemSeparator}
renderItem={renderItem(navigate)} // <-- pass navigate
keyExtractor={(item) => item.id}
/>
);
};
Alternatively you could move the renderItem function declaration into the NoteList component so the navigate function is just closed over in callback scope.
const ItemSeparator = () => <View style={styles.separator} />;
const NoteList = ({ notes }) => {
const navigate = useNavigate();
const renderItem = ({ item }) => (
<View style={styles.item}>
<Pressable onPress={() => navigate(`/${item.id}`)}>
<Text fontWeight="bold" fontSize="subheading">
{item.title}
</Text>
<Text>{item.body}</Text>
</Pressable>
</View>
);
return (
<FlatList
data={notes}
ItemSeparatorComponent={ItemSeparator}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
);
};

#gorrhom React Native Bottom Sheet - Calling from another component

Im trying to implement this relatively popular bottom sheet in React Native by #gorhom.
My aim is to open the bottom sheet from another component. I've tried to follow this answer - here . However, i do not understand what goes in the touchable opacity onPress in my component where it is being called from.
Code below
BottomSheetModalComponent
export default function BottomSheetModalComponent({ref}) {
// ref
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
// variables
const snapPoints = useMemo(() => ['25%', '50%'], []);
// callbacks
const handlePresentModalPress = useCallback(() => {
ref.current?.present();
}, []);
const handleSheetChanges = useCallback((index: number) => {
console.log('handleSheetChanges', index);
}, []);
// renders
return (
<BottomSheetModalProvider>
<View>
<BottomSheetModal
ref={ref}
snapPoints={snapPoints}
onChange={handleSheetChanges}
>
<View>
<Text>Awesome 🎉</Text>
</View>
</BottomSheetModal>
</View>
</BottomSheetModalProvider>
);
};
Location Component
export default function LocationBar() {
// Create Ref
const userBottomSheetRef = useRef<BottomSheetModal>(null);
// Pass ref into the bottom sheet component
<LocationBottomSheet ref={userBottomSheetRef} snapPoints={["30%"]}/>
return (
<>
<View style={{ flexDirection: "row" }}>
<View style={styles.locationBar}>
<Octicons style={styles.locationIcon} name="location" size={18} />
<TouchableOpacity onPress={() => {
//WHAT GOES HERE?
}}>
<Text style={{fontSize: 17, fontWeight: '600'}}>{userLocation}</Text>
</TouchableOpacity>
<Ionicons style={styles.chevronIcon} name="chevron-down" size={12} />
</View>
</View>
</>
);
}
Thanks in advance

How can I pass a variable to the previous screen by using React Navigation?

I'm using React Native. I tried to write this code:
//Screen A
//ignored the "import"
export function Hoge(Props) {
let onSelect = false
return(
<View>
<View>
<Text>{onSelect ? 'Selected' : 'Not Selected' }</Text>
</View>
<TouchableOpacity
onPress={() => {
navigation.navigate('ScreenB', { onSelect: onSelect });
}};>
<View><Text>Screen B</Text></View>
</TouchableOpacity>
</View>
)
}
//ScreenB
export function HogeHoge(Props) {
const [hoge, setHoge ] = useState(route.params.onSelect)
function goBack() {
setHoge(true)
navigation.goBack();
}
let screen = navigation.setOptions({
headerLeft: () => (
<TouchableOpacity onPress={() => {
goBack();
}}>
<Image
source={require('../../images/back_btn.png')}
style={commonStyles.back_btn}
/>
</TouchableOpacity>
),
})
return (
<View>{screen}</View>
)
};
referring to the following: https://github.com/react-navigation/react-navigation/issues/288
I hoped the "onSelect" is true, but it was false. How can I fix it?

Adding item click event in react native Grid View

Please find my code below and help me for adding item click listener for the items in the grid view. Please find the link which I followed library link.
And I need to display the name in an alert when the user clicks on each item in the gridlist. Styles are not included in the code
Thanks in Advance
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableWithoutFeedback
} from 'react-native';
import GridLayout from 'react-native-layout-grid';
class HomeScreen extends Component {
renderGridItem = (props) => (
<View style={styles.item} >
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</View>
);
render() {
const items = [];
for (let x = 1; x <= 30; x++) {
items.push({
name: `Grid ${x}`
});
}
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Grid Layout
</Text>
<View style={styles.flex}>
<GridLayout
items={items}
itemsPerRow={2}
renderItem={this.renderGridItem}>
</GridLayout>
</View>
</View>
);
}
}
export default HomeScreen;
Instead of using <View> in your renderGridItem, you could use one of the touchables component (react native doc).
For example with <TouchableOpacity >:
renderGridItem = (props) => (
<TouchableOpacity style={styles.item} onPress={() => this.showAlert(props.name)}>
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</TouchableOpacity>
);
showAlert = (name) => {
Alert.alert(
'Alert Title',
`The user name is: ${name}`,
[
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{ cancelable: false }
)
}
Why don't you wrap renderGridItem in a TouchableWithoutFeedback?
renderGridItem = (props) => (
<TouchableWithoutFeedback onPress={()=> Alert.alert(props.name)}>
<View style={styles.item} >
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</View>
<TouchableWithoutFeedback />
);
Also you will need to import Alert from react-native.

React Native FlatList only responds to touches sometimes

I have used FlatList in multiple places in my app previously without any issues, but now when I created a new one it doesn't seem to register touches/swipes correctly. Only like 1/6 touches seem to register.
See the video here: https://photos.app.goo.gl/NZCtVYX6GLVCQN392
This is how I use the FlatList:
render() {
return (
<Container>
...
<FlatList
data={this.state.exercises}
renderItem={({item}) =>
<SetsRepsAndWeightItem exercise={item}/>
}
keyExtractor={item => item.name}
style={style.list}
/>
</Container>
);
}
And the SetsRepsAndWeightItem:
render() {
return (
<View style={style.container}>
<View style={style.header}>
<Text style={style.headerText}>{this.props.exercise.name}</Text>
</View>
<View style={style.about}>
<TouchableWithoutFeedback onPress={this.handleSetsPressed}>
<StatisticNumber metric="Sets" value={7}/>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={this.handleRepsPressed}>
<StatisticNumber metric="Reps" value={5}/>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={this.handleWeightPressed}>
<StatisticNumber metric="kg" value={35}/>
</TouchableWithoutFeedback>
</View>
</View>
);
}
handleSetsPressed = () => {
console.log("sets pressed");
}
handleRepsPressed = () => {
console.log("reps pressed");
}
handleWeightPressed = () => {
console.log("weight pressed");
}
Also: the TouchableWithoutFeedback elements are not calling their onPress functions when they are touched.
The Container is as simple as this:
export default class Container extends Component {
static propTypes = {
children: Proptypes.any,
backgroundColor: Proptypes.string
};
render() {
const containerStyles = StyleSheet.flatten([
style.container,
this.props.backgroundColor ? { backgroundColor: this.props.backgroundColor } : null,
]);
return (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View style={containerStyles}>
{this.props.children}
</View>
</TouchableWithoutFeedback>
);
}
}
The following two fixes solved the issues for me:
Remove the onPress={() => Keyboard.dismiss()} from the Container component
Move the TouchableWithoutFeedback into the StatisticNumber component, and pass onPress as a prop from SetsRepsAndWeightItem

Resources