React Native Pressable has to be clicked twice to be executed - firebase

I am using react native and firebase v9. When I click to add a chatroom, an alert prompt pops up, the user enters a room name and firebase should automatically roll it out to the UI. But what happens is when the modal is closed, I then have to click the add button again and then the chat room will roll out. How can I fix this so when the user enters a name, presses ok it automatically shows on the UI? Thanks!
My state:
const [rooms, setRooms] = useState([]);
const [input, setInput] = useState("");
Here is my JSX:
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<Pressable onPress={handleAddRoom}>
<View style={styles.addRoom}>
<MaterialCommunityIcons
name="plus-circle"
color="black"
size={42}
/>
<Text style={styles.nameText}>Add</Text>
</View>
</Pressable>
Here are my functions for uploading to firebasev9:
const handleAddRoom = () => {
Alert.prompt("Add New Chat Room", "Please enter a name", [
{ text: "CANCEL", onPress: null },
{ text: "OK", onPress: (text) => setInput(text) },
]);
if (input) {
const colRef = collection(db, "rooms");
addDoc(colRef, {
image: inputData,
roomName: input,
});
}
setInput("");
};
const fetchRooms = async () => {
try {
const colRef = query(collection(db, "rooms"), orderBy("roomName", "asc"));
onSnapshot(colRef, (snapshot) => {
setRooms(
snapshot.docs.map((doc) => ({
id: doc.id,
roomName: doc.data().roomName,
image: doc.data().image,
}))
);
});
} catch (err) {
console.log(err);
}
};
useEffect(() => {
fetchRooms();
}, []);

Related

MUI snackbar div persist on DOM after being closed

I created a global modal with the purpose of only calling it when I need it, but the problem is that the snackbar div persists in the DOM and this causes certain elements to be blocked because they are below this div. Any idea what the problem would be?
My GlobalAlert component:
export function GlobalAlert() {
const {alertState, handleClose} = useAlertContext();
const {open, type, message} = alertState;
function TransitionDown(props: TransitionProps) {
return <Slide {...props} direction="down" />;
}
return (
<Snackbar
key={"top" + "center"}
TransitionComponent={TransitionDown}
anchorOrigin={{vertical: "top", horizontal: "center"}}
autoHideDuration={4000}
disableWindowBlurListener={true}
open={open}
onClose={handleClose}
>
<Alert severity={type} sx={useStyles.alert} variant="filled" onClose={handleClose}>
{message}
</Alert>
</Snackbar>
);
}
Context where I get the info
const AlertContextProvider = (props: any) => {
const [alertState, setAlertState] = React.useState<AlertState>({
open: false,
type: "error",
message: "",
});
const handleClose = React.useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === "clickaway") {
return;
}
setAlertState({
open: false,
type: "error",
message: "",
});
}, []);
const value = React.useMemo(
() => ({
alertState,
setAlertState,
handleClose,
}),
[alertState, handleClose],
);
return <AlertContext.Provider value={value} {...props} />;
};
Bug image

Accessing URL to use issues (expo/react native app/firebase)

In my current app i want the user to pick a photo from their phone and then to use the downloadable url from firebase storage to then add it to my database. Everything works but when a user(when they first time to pick a image) it says
TypeError: Network request failed
code(logic/state/functions):
const [image, setImage] = useState(null);
const [url, setUrl] = useState(null)
async function postImage () {
try {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
imgFirebase()
setImage(result.assets[0].uri); }
}
catch(E) {
Alert.alert(
"Alert Title",
"My Alert Msg 1",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{ text: "OK", onPress: () => console.log("OK Pressed") }
]
);
}
}
async function imgFirebase () {
try {
console.log(image);
const d = await fetch(image)
const dd = await d.blob()
const fileName = image.substring(image.lastIndexOf("/")+1)
const storage = getStorage();
const storageRef = ref(storage, fileName);
uploadBytes(storageRef,dd).then((snapshot) => {
getDownloadURL(snapshot.ref).then(async (url) => {
// Create a query against the collection.
setUrl(url)
console.log(url)
}).catch(e=>{
Alert.alert(
"Alert Title",
"My Alert Msg 2",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel"
},
{ text: "OK", onPress: () => console.log("OK Pressed") }
]
);
})
});
}
catch(e) {
alert(e)
}
}
code(for rendered UI):
<Pressable color="#000" style={{marginTop:20,backgroundColor:"#FF35F0",padding:10,borderRadius:11,color:"#000"}} onPress={postImage}>
<Text style={{color:"#fff",textAlign:"center",fontSize:20}}>Pick Image</Text>
</Pressable>
whats also weird is that after the first time getting this error and then trying to pick a image the error finally goes away. Why does this error come up at first? How would i fix this?

read data from firebase realtime database using react native

I want to read data from firebase realtime database.
I want to fix my "function readData()"
like,
If I use this funcion, I want to read my data, without enter "username".
for example, I created this,
username:hello,
email:hello#gmail.com
and If I press "read data" button, (without enter 'username')
I want to read recent data. (username and email both)
please help me!
this is my app.js
import { StatusBar } from 'expo-status-bar';
import { useState } from 'react';
import { Button, button, StyleSheet, Text, TextInput, View } from 'react-native';
import { ref, set, update, onValue, remove } from "firebase/database";
import { db } from './components/config';
export default function App() {
const [username, setName] = useState('');
const [email, setEmail] = useState('');
function createData() {
set(ref(db, 'users/' + username), {
username: username,
email: email
}).then(() => {
// Data saved successfully!
alert('data created!');
})
.catch((error) => {
// The write failed...
alert(error);
});
}
function update() {
set(ref(db, 'users/' + username), {
username: username,
email: email
}).then(() => {
// Data saved successfully!
alert('data updated!');
})
.catch((error) => {
// The write failed...
alert(error);
});
}
function readData() {
const starCountRef = ref(db, 'users/' + username);
onValue(starCountRef, (snapshot) => {
const data = snapshot.val();
setEmail(data.email);
});
}
return (
<View style={styles.container}>
<Text>firebase</Text>
<TextInput value={username} onChangeText={(username) => {setName(username)}} placeholder='Username' style={styles.TextBoxes}></TextInput>
<TextInput value={email} onChangeText={(email) => {setEmail(email)}} placeholder='Email' style={styles.TextBoxes}></TextInput>
<Button title='create data' onPress={createData}></Button>
<Button title='update data' onPress={update}></Button>
<Button title='read data' onPress={readData}></Button>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
TextBoxes: {
width:'90%',
fontSize:18,
padding:12,
backgroundColor:'grey',
marginVertical:10,
}
});
I understand you want to call last username by default if username is empty.
For this, you can define lastUserName state and call it if username is empty, for example;
const [lastUserName, setLastUserName] = useState('');
readData() ,
function readData() {
const starCountRef = ref(db, 'users/' + username !== '' ? username : lastUserName);
onValue(starCountRef, (snapshot) => {
const data = snapshot.val();
setEmail(data.email);
});
}
Then, view should be like that;
<View style={styles.container}>
<Text>firebase</Text>
<TextInput value={username}
onChangeText={(username) => {
setName(username)
setLastUserName(username) // add this line
}
}
placeholder='Username' style={styles.TextBoxes}></TextInput>
<TextInput value={email} onChangeText={(email) => {setEmail(email)}} placeholder='Email' style={styles.TextBoxes}></TextInput>
<Button title='create data' onPress={createData}></Button>
<Button title='update data' onPress={update}></Button>
<Button title='read data' onPress={readData}></Button>
</View>
Note : If you want to keep this state in global use Redux.
Note: Use localStorage if you want the application to run on the same state after closing and reopening. see: https://github.com/react-native-async-storage/async-storage

I get the error 'Error: Request failed with status code 408' when attempting to make stripe payment in production

I am trying to make stripe payments in my react native app using the stripe.charges.create function and library axios. This currently works fine in test mode, so using the secret and publishable test keys. However, when amending the keys to live as well as changing the source I get the following error: [Error: Request failed with status code 408] .
Looking at the stripe docs https://stripe.com/docs/api/errors it appears that this may be due to a missing parameter, ...'Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.).'
Could I be missing the customer id in my stripe.charges.create function shown below? The stripe docs mentions that for card sources the customer id is required, https://stripe.com/docs/api/charges/create . If this is required where do I add this in my code in order to make live payments? API Keys obtained from stripe dashboard.
Testing
index.js file
const stripe = require("stripe")("**SK_TEST**");
exports.payWithStripe = functions.https.onRequest((request, response) => {
stripe.charges
.create({
amount: request.body.amount,
currency: request.body.currency,
source: "tok_mastercard",
})
.then((charge) => {
response.send(charge);
})
.catch((err) => {
console.log(err);
});
});
Production
index.js file
const stripe = require("stripe")("SK_LIVE");
exports.payWithStripe = functions.https.onRequest((request, response) => {
stripe.charges
.create({
amount: request.body.amount,
currency: request.body.currency,
source: "request.body.token",
})
.then((charge) => {
response.send(charge);
})
.catch((err) => {
console.log(err);
});
});
CardScreen.js file
import React, { PureComponent } from "react";
import { View, Text, StyleSheet } from "react-native";
import stripe from "tipsi-stripe";
import Button from "./components/Button";
import { demoCardFormParameters } from "./demodata/demodata";
import axios from "axios";
stripe.setOptions({ publishableKey: "PK_LIVE" });
export default class CardScreen extends PureComponent {
static title = "Card Form";
state = {
loading: false,
paymentMethod: null,
};
handleCardPayPress = async () => {
try {
this.setState({ loading: true, paymentMethod: null });
const paymentMethod = await stripe.paymentRequestWithCardForm({
smsAutofillDisabled: true,
});
this.setState({ loading: false, paymentMethod });
} catch (error) {
this.setState({ loading: false });
}
};
makePayment = async () => {
this.setState({ loading: true });
axios({
method: "POST",
url: "https://us-central1-appname-90059.cloudfunctions.net/payWithStripe",
data: {
amount: 50,
currency: "gbp",
token: this.state.paymentMethod,
},
})
.then((response) => {
console.log(response);
this.setState({ loading: false });
})
.catch((err) => {
console.log(err);
});
};
render() {
const { loading, paymentMethod } = this.state;
return (
<View style={styles.container}>
<Text style={styles.header}>Card Form Example</Text>
<Text style={styles.instruction}>
Click button to show Card Form dialog.
</Text>
<Button
text="Enter your card and pay"
loading={loading}
onPress={this.handleCardPayPress}
/>
<View style={styles.paymentMethod}>
{paymentMethod && (
<>
<Text style={styles.instruction}>
Payment Method: {JSON.stringify(paymentMethod.id)}
</Text>
<Button
text="Make Payment"
loading={loading}
onPress={this.makePayment}
/>
</>
)}
</View>
</View>
);
}
}
Thanks.

Redux devtools won't catch specific actions

I'm loading it like that:
const store = createStore(
AppReducer,
composeEnhancers(applyMiddleware(createDebounce(), thunkMiddleware,
websocketMiddleware)),
);
I've got the following action:
export const toggleCardLayersMenu = (index, value) => ({
type: "CARD:TOGGLE_LAYERS_MENU",
index: index,
value: value,
});
Which I dispatch something to open a menu and something to close it.
Now, the chrome extension display the action with a small delay if the action is used to open the menu, and won't display the action at all if it's used to close the menu.
It occurs only with that specific action. What are the possible causes, and what can be done?
Edit:
This is where I dispatch the action:
...
<IconButton
onClick={ e => dispatches.toggleCardLayersMenu(e.currentTarget) }
><LayersIcon />
</IconButton>
<Menu
anchorEl={ card.menuBtnElem }
open={ card.isMenuOpen }
onRequestClose={ () => dispatches.toggleCardLayersMenu(null) }
style={ styles.menu }
>
...
This is the dispatchToProps():
const mapDispatchToProps = (dispatch, ownProps) => ({ dispatches: {
updateCardLayers(value) {
dispatch(displayActions.updateCardLayers(ownProps.index, value));
},
toggleCardLayersMenu(value) {
dispatch(displayActions.toggleCardLayersMenu(ownProps.index, value));
},
...

Resources