onClick() doesn't trigger function in React-Native App - javascript

In my react-native mobile app I have written a component called Row in row.js that contains a TouchableOpacity with an onClick() event handler. However when the component is clicked the function doesn't run.
The Row component displays some text about a particular film and should run the handlePress() function when clicked:
const Row = props => (
<TouchableOpacity onClick={() => props.handlePress(props.imdbID)} style={styles.row}>
<Text>Some text</Text>
</TouchableOpacity>
)
In a separate app.js file, the handlepress function has been written and is passed to the Row component as a prop. The imdbID variable is also passed to the component from the film object:
handlePress = imdbID => {
// do something with imdbID
}
<Row handlePress={this.handlePress} {...film} />
Please can someone tell me what I am doing wrong and why the function doesn't run.

If you take a look at the docs, it doesnt have onClick.
You should use onPress.
const Row = props => (
// using onPress
<TouchableOpacity onPress={() => props.handlePress(props.imdbID)} style={styles.row}>
<Text>Some text</Text>
</TouchableOpacity>
)

React-Native doesnt provide onClick functionality , it gives onPress instead , so replace onClick with onPress
const Row = props => (
<TouchableOpacity onPress={() => props.handlePress(props.imdbID)} style={styles.row}>
<Text>Some text</Text>
</TouchableOpacity>
)
hope this helps ,feel free for doubts

Use onPress() instead of of onClick()
improved code
const Row = props => (
<TouchableOpacity onPress={()=> props.handlePress(props.imdbID)} style={styles.row}>
<Text>Some text</Text>
</TouchableOpacity>
)

Use onPress instead of onClick and be sure you are importing touchable from react-native not gesture-handler

React native does not have onClick for TouchableOpacity.
Use onPress instead.

Related

Modal not updating to new item in array,firebase/react native state

my current issue with my react native app is that when a user wants to open a lesson (from the lessons array with each object being a lesson with a title,description,img url etc)to make it bigger through a modal, its state does not update. What i Mean by this is that the books title,description,and other attributes won't change if you press on a new lesson. What would be the solution to this?
export default function Learn() {
const [modalVisible, setModalVisible] = useState(false);
const [lessons,setLessons] = useState()
useEffect(() => {
async function data() {
try {
let todos = []
const querySnapshot = await getDocs(collection(db, "lessons"));
querySnapshot.forEach((doc) => {
todos.push(doc.data())
});
setLessons(todos)
console.log(lessons)
}
catch(E) {
alert(E)
}
}
data()
}, [])
return (
<View style={learnStyle.maincont}>
<View>
<Text style={{fontSize:28,marginTop:20}}>Courses</Text>
<ScrollView style={{paddingBottom:200}}>
{lessons && lessons.map((doc,key) =>
<>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Image source={{
uri:doc.imgURL
}} style={{width:"100%",height:300}}/>
<Text style={{fontWeight:"700",fontSize:25}}>{doc.title}</Text>
<Text style={{fontWeight:"700",fontSize:16}}>{doc.desc}</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</Pressable>
</View>
</View>
</Modal>
<LessonCard setModalVisible={setModalVisible} title={doc.title} desc={doc.desc} img1={doc.imgURL} modalVisible={modalVisible}/>
</>
)}
<View style={{height:600,width:"100%"}}></View>
</ScrollView>
</View>
</View>
)
}
What it looks like:
**image 1 is before you press the modal and the 2nd one is after
**the main issue though is that if you press cancel and press on another lesson the modal that opens has the the same state(title,imgurl,anddesc) as the first lesson and does not change.
The problem is that you create a lot of modal windows through the map function, I suggest making one window and passing the key as a parameter and using it to search for a specific array of data that is shown to the user (photo, title, etc.)
The problem is that all 3 Modals are controlled by the one state variable. So when the code sets modalVisible to true, all 3 modals are being opened at once.
You can fix this in a few ways, but a simple way would be to move the Modal and its state into the LessonCard component. This way each modal will have its own state that's only opened by its card. So the loop in Learn will just be:
{lessons && lessons.map((doc,key) => (
<LessonCard lesson={doc} key={key} />
)}
Adding to address question in comments
LessonCard should not accept setModalVisible or modalVisible props. The
const [modalVisible, setModalVisible] = useState(false);
should be inside LessonCard, not Learn. That way each Card/Modal pair will have its own state.
Additionally, although React wants you to pass the key into LessonCard in the map function, LessonCard should not actually use the key prop for anything. See https://reactjs.org/docs/lists-and-keys.html#extracting-components-with-keys
So, the LessonCard declaration should just be something like
export default function LessonCard({lesson}) {

React Native - Unable to pass body from onPress to action function in Context

Thanks in advance, everyone. Total newbie to react native. Using functional components only at this point.
In AddGuestScreen.js I am capturing this TextInput and submitting {guestA} to the action in TeeTimeContext.js
<View style={styles.boxContainer}>
<Text style={styles.large}>Guest Name:</Text>
<TextInput
style={styles.input}
value={guestA}
onChangeText={(text) => setGuestA(text)}
autoCorrect={false}
/>
</View>
<View style={[styles.butttonContainer, styles.mainButton]}>
<Button
title='Save'
color='white'
onPress={ ({guestA}) => addGuestSave({guestA}) }
/>
</View>
guestA is being passed as undefined from the onPress method and I don't understand why.
Thanks so much for any help.
The onPress event from the Button doesn't have the property guestA.
You can define a function for the button and pass in guestA inside AddGuestScreen before the return like so:
_handlePress = () => {
addGuestSave(guestA);
};
And then pass the function to the Button
<Button onPress={_handlePress} ... />

Passing item.name in StackNavigator React Native

So i have a flatList that display names using Fetch api,
<FlatList
data={this.state.data}
keyExtractor={item => item.id}
renderItem={({item}) => <TouchableOpacity onPress {()=>NavigationService.navigate('Med') }>
<Text> {item.name}</Text>)}
on the click on one of the name i navigate to another screen where i wil have to use "item.name", how can i pass this param.on that screen code i'm using a class and i don't want to use a function.
class search extends React.Component {
constructor(props){
super(props);
}.....
thanks in advance
check hope it will work
now here is pass your item.name in this navigate action
<FlatList
data={this.state.data}
keyExtractor={item => item.id}
renderItem={({item}) => <TouchableOpacity onPress {()=>NavigationService.navigate(`${item.name}`) }>
<Text> {item.name}</Text>)}
Since your NavigationService handle navigate function with params as below,
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
You can pass your params as
<TouchableOpacity onPress {() => NavigationService.navigate('Med', {name: item.name})}>
Once you navigate to the specific screen you can access you name params as
this.props.route.params.name
Hope this helps you. Feel free for doubts.

Same Function is Triggered IN Multiple Components

I'm using react-native-material-menu's popup for showing menu options.
But the issue is, it's not working for multiple scenarios.
I mean when I click on first menu button, the same methods gets triggered and hence the same menu is opened every time.
What should be the better approach for to handle this particular scenario.
Here is the Snack
_menu = null;
setMenuRef = ref => {
this._menu = ref;
};
hideMenu = () => {
this._menu.hide();
};
showMenu = () => {
this._menu.show();
};
{this.state.clientsList.map((item) => {
return (
<View style={styles.caseItem} >
<Card style={styles.card}>
<CardItem>
<Body>
<View style={styles.rowTitle}>
<Text style={styles.title}>{item.FullName}</Text>
<Menu
ref={this.setMenuRef}
button={<Icon type="Feather" name="more-vertical" onPress={this.showMenu} style={{ fontSize: 20, color: '#555' }} />}
>
<MenuItem onPress={this.hideMenu}>View</MenuItem>
<MenuItem onPress={this.hideMenu}>Edit</MenuItem>
<MenuItem onPress={this.hideMenu}>Delete </MenuItem>
</Menu>
</View>
<View>
<Text style={styles.lbl}>Email: <Text style={styles.lblValue}>{item.EmailID}</Text></Text>
<Text style={styles.lbl}>Client Type: <Text style={styles.lblValue}>{item.ClientType}</Text></Text>
</View>
</Body>
</CardItem>
</Card>
</View>
);
})}
you are using same reference for all menu components
you have to use different ref for every Menu.
Best Approach:
first way to Create HOC for Menu and handle them in it.
Moderate
or Create Dynamic Ref in React for Menu's List
for running code only
3rd is to create ref for every menu
_menu1 = null;
_menu2 = null;
_menu3 = null;
You are calling the same ref every-time. I've not used the library you mentioned but if it has to rely on ref you can create a list of reference instead, syntax is in this post.

Is there a way to have "onPress" and "onLongPress" on same "Button/TouchableOpacity"

I am wondering if there is a way to have onPress and onLongPress on the same button/TouchableOpacity, in react-native with javascript,
If so how do I do that?
Yes, according to the docs, you can add an onPress and onLongPress props.
For the record, TouchableOpacity inherits all the props available on TouchableWithoutFeedback.
<TouchableOpacity
onPress={() => { console.log("onPress") }}
onLongPress={() => { console.log("onLongPress") }}
>
...
</TouchableOpacity>

Categories

Resources