Return JSX component onPress react-native - reactjs

I want to prompt users to get input onPress but returning JSX from an onPress never worked so whats a possible workaround to return JSX based on button click. Here's my code:
import React, { useState } from 'react';
import {
StyleSheet,
KeyboardAvoidingView,
View,
Text,
TouchableOpacity
} from 'react-native';
import InputPrompt from './InputPrompt'
const Newact = (props) => {
const [visible, setVisible] = useState(false)
return(
<View>
<View style={styles.button} >
<TouchableOpacity style={styles.center} onPress={getTitle}>
<Text style={styles.plusSign}>+</Text>
</TouchableOpacity>
</View>
</View>
);
}
const getTitle = () =>{
return(
<InputPrompt />
)
}
Update:
Now thats how my code looks:
const Newact = props => {
const [prompt, setPrompt] = useState(false);
return(
<View style={styles.button} >
<TouchableOpacity style={styles.center} onPress={() => setPrompt(true)}>
<Text style={styles.plusSign}>+</Text>
</TouchableOpacity>
{prompt ? <InputPrompt setPrompt={setPrompt} /> : null}
</View>
);
}
and InputPrompt component is:
const InputPrompt = (props) => {
const [name, setName] = useState('');
return(
<View>
<DialogInput
title={"New Activity"}
submitText={"Add"}
hintInput ={"Enter activity name....."}
submitInput={ (inputText) => {setName(inputText), props.setPrompt(false)} }
closeDialog={ () => {props.setPrompt(false)}}>
</DialogInput>
<Text>{name}</Text>
</View>
);
}

When they press, you should set state. This causes the component to rerender, and on that new render you can return JSX describing what you want the screen to look like. I'm not sure exactly where you want to render the input prompt, but maybe something like this:
const Newact = (props) => {
const [visible, setVisible] = useState(false)
const [prompt, setPrompt] = useState(false);
return (
<View>
<View style={styles.button} >
<TouchableOpacity style={styles.center} onPress={() => setPrompt(true)}>
<Text style={styles.plusSign}>+</Text>
</TouchableOpacity>
</View>
{prompt && <InputPrompt />}
</View>
);
}

Updating the state onPress is a simple way of achieving this as it will then re-render the component and you can run any jsx based on that state that you updated.
You can use a ternary expression
{isPressed ? <return your jsx here> : null}
this is what it will look like in your case
const Newact = (props) => {
const [visible, setVisible] = useState(false)
const [prompt, setPrompt] = useState(false);
return (
<View>
<View style={styles.button} >
<TouchableOpacity style={styles.center} onPress={() => setPrompt(true)}>
<Text style={styles.plusSign}>+</Text>
</TouchableOpacity>
</View>
{prompt ? <InputPrompt /> : null}
</View>
);
}

You need to change your code to something like this:
const Newact = props => {
const [visible, setVisible] = useState(false);
const getTitle = () => {
setVisible(true);
}
return (
<View>
<View style={styles.button}>
<TouchableOpacity style={styles.center} onPress={getTitle}>
<Text style={styles.plusSign}>+</Text>
</TouchableOpacity>
{
visible && <InputPrompt />
}
</View>
</View>
);
};

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}
/>
);
};

How do I get information from the database using another user's userId?

What I want to do is to access the data of the person who sent the post using user id. I can get the id but I can't use it to pull information from the database
I got the id of the person who shared the post
After getting the id of the person who shared the post, I want to use the id to pull the information from the database, but it acts as if there is no id.
const user = firebase.auth().currentUser.uid;
const db = firebase.database();
const ref = db.ref('kullaniciBilgiler/'+`${user}`);
const refComment = db.ref('yorumlar/'+`${user}`+'/commentData');
const refPost = db.ref('Post')
export default postDetails = ({navigation, route}) => {
const [currentDate, setCurrentDate] = useState('');
const [userId, setUserId] = useState('');
const [commentName, setcommentName] = useState([]);
const [commentText, setcommentText] = useState('');
const [commentData, setcommentData] = useState([]);
const [postDetailsData, setpostDetailsData] = useState([]);
const [postingInf, setPostingInf] = useState([]);
const { title } = route.params;
//console.log(title)
function getComments(){
const refComment = db.ref('yorumlar/'+`${user}`+'/commentData');
refComment.on("value",(snapshot)=>{
if(snapshot.val()){
const data=snapshot.val();
const comments=Object.values(data) || [];
//console.log(data);
setcommentData(comments)
}
})
}
function getPostingInf(){
const refPostingİnf = db.ref('kullaniciBilgiler/'+ userId);
refPostingİnf.on("value",(snapshot)=>{
if(snapshot.val()){
const data=snapshot.val();
const comments=Object.values(data) || [];
console.log(data);
setPostingInf(comments)
}else{
alert('zot')
}
})
} ///SORUNLU KISIM
function getPost(){
var list=[];
refPost.child(title).on("value",(snapshot)=>{
if(snapshot.val()){
list.push({
text:snapshot.val().text,
id:snapshot.val().id,
postTime:snapshot.val().postTime,
title:snapshot.val().title,
category:snapshot.val().category
}
);
setpostDetailsData(list);
//console.log(snapshot.val().text)
//console.log(child.val().title,'tamam',child.val())
//const data =snapshot.val();
//const postDetails = Object.values(data) || [];
//setpostDetailsData(postDetails);
//console.log(data)
}else{
//console.log('eşleşmedi')
}
});
}
ref.once('value').then(snapshot=>{
var li=[]
var list=[]
snapshot.forEach((child) => {
li.push({
name : child.val().name,
surname : child.val().surname,
})
list.push(
child.val().name + ' '+ child.val().surname
)
}
)
setfirebaseData(li)
setcommentName(list)
//console.log(list);
});
getComments();
getPost();
getPostingInf();
} , []);
return(
<SafeAreaView style={styles.container}>
<ScrollView>
<View style={styles.headerBarView}>
<TouchableOpacity style={{position: 'absolute', left:10}}>
<Icon name='arrow-left'
style={styles.Icons}
/>
</TouchableOpacity>
<TouchableOpacity style={{position: 'absolute', right:60}
}>
<Icon name='bookmark'
style={styles.Icons}
/>
</TouchableOpacity>
<TouchableOpacity style={
{position: 'absolute', right:10}}>
<Icon name='share-square'
style={styles.Icons}
/>
</TouchableOpacity>
</View>
<Card style={{marginBottom:5}}>
<FlatList
data={postDetailsData}
keyExtractor={(item)=>item.key}
renderItem={({item,index})=>{
setUserId(item.id)
return(
<View style={styles.questionBoxView}>
<View style={styles.questionTitleView}>
<Text style={styles.questionTitleText}>
{item.title}
</Text>
</View>
<View style={styles.questionerProfileView}>
<Image source={{uri:'https://picsum.photos/700'}}
style={styles.AvatarImage}
/>
<Text style={styles.UserNameText}>{item.name+' '+item.surname}</Text>
<TouchableOpacity style={styles.followPosterTouch}>
<Text style={styles.followPosterTouchText}>Takip Et</Text>
</TouchableOpacity>
</View>
<View style={styles.questionDetailsView}>
<Text style={{fontSize:15,padding:10}}>{item.text}</Text>
</View>
<View style={styles.categoryBoxes}>
{item.category.map((a,b)=>{
return <TouchableOpacity
style={styles.categoryBoxesTouch}
>
<Text style={styles.categoryBoxesText}>{a.name}</Text>
</TouchableOpacity>
})}
</View>
</View>
)
}
}
/>

Navigation not working on custom button react native

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>
);
};

How to show Modal in React Native using Functional Component imported from another file

I am showing a view Login.js and in that view on button click, I need to render modal, that I have separated and written in another file named Countries.js.
On Login.js file I have imported Countries.js and on button click, I am doing this:
show_modal = () => {
<Countries/>
}
but nothing is happening. I am a noob I just started React Native kindly help me.
Countries.js code:
import React, { Component, useState } from "react";
import {
Alert,
Modal,
Text,
TouchableHighlight,
View
} from "react-native";
const Countries = () => {
console.log('called');
const [modalVisible, setModalVisible] = useState(true);
return (
<View style={styles.centeredView}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {
setModalVisible(!modalVisible);
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<TouchableHighlight
style={styles.openButton}
onPress={() => {
setModalVisible(true);
}}
>
<Text style={styles.textStyle}>Show Modal</Text>
</TouchableHighlight>
</View>)
};
export default Countries;
Login.js
import React, { Component, useState } from "react";
import {Modal, View, Text, TouchableHighlight} from 'react-native';
import CountryModal from 'path to outsource country modal file';
const login = (props)=>{
const [modalVisible, setModalVisible] = useState(true);
return(
<View>
<TouchableHighlight
style={styles.openButton}
onPress={() => {
setModalVisible(true);
}}
>
<Text style={styles.textStyle}>Show Modal</Text>
</TouchableHighlight>
<CountryModal isVisible={modalVisible} setModalVisiblity = {()=>{setModalVisible(preState=> preState = !preState)}}>
</View>
)
}
export default login;
Country Modal file
import React from react;
import {Modal} from 'react-native';
const Country = (props)=>{
return (
<Modal
animationType="slide"
transparent={true}
visible={isVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<TouchableHighlight
style={{ ...styles.openButton, backgroundColor: "#2196F3" }}
onPress={() => {props.setModalVisiblity
}}
>
<Text style={styles.textStyle}>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
)
}
Hope you got your answer.
Change this
show_modal = ()=> {
<Countries/>
}
to this
show_modal = ()=> {
return <Countries/>; // add return keyword
}
the above function will return undefined if return id not explicitly defined
You need to have this modal directly with other components.
Example code
export default function Login() {
const [modalVisible, setModalVisible] = useState(false);
return (
<View>
<Button title="Toggle Modal" onPress={() => setModalVisible(!modalVisible)}
// other login page code
<Countries visible={visible} /> // or any other modal, add direclty to the screen you need to show the modal at
</View>
)
}

Invalid use of hooks when calling component with onPress

I'm trying to work with modals when I click on a button from the header.
Say I have this component List, and List is using custom navigation options:
import { CustomModal } from './components/Modal';
const List = (props) => {
const [enteredUrl, setEnteredUrl] = useState('');
const urlInputHandler = (enteredUrl) => {
setEnteredUrl(enteredUrl);
};
const addUrlHander = () => {
console.log(enteredUrl);
}
return (
<View></View>
);
};
List.navigationOptions = (navData) => {
return {
headerTitle: 'Workouts',
headerRight: (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title='Add'
iconName='md-add'
onPress={() => {
CustomModal(); //here is the modal
}}
/>
</HeaderButtons>
),
headerBackTitle: null
};
};
My Modal component has this:
export const CustomModal = (props) => {
const [modalVisible, setModalVisible] = useState(false);
console.log(props);
return (
<Modal
animationType='slide'
transparent={false}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight
onPress={() => {
setModalVisible(!modalVisible);
}}
>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
);
}
But it is giving me the invalid hook error. Why is it that my onPress in my navigationOptions giving me this? Am I doing this wrong?
onPress is a callback, you can't put components in it. Probably what you want is something like this:
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<CustomModal/>
</HeaderButtons>
and the modal looks like
export const CustomModal = (props) => {
const [modalVisible, setModalVisible] = useState(false);
console.log(props);
return modalVisible?(
<Modal
animationType='slide'
transparent={false}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}
>
<View style={{ marginTop: 22 }}>
<View>
<Text>Hello World!</Text>
<TouchableHighlight
onPress={() => {
setModalVisible(!modalVisible);
}}
>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
):(
<Item
title='Add'
iconName='md-add'
onPress={() => setModalVisible(!modalVisible)}
/>
);
}

Resources