React Native, Stack Navigation Group for Firebase authentication stay logged in - firebase

I made a registration, login and home screen integrating firebase on React-Native. They all works fine, and now I'm trying to allow users to stay logged in even if they close the app. I do it by using on onAuthStateChanged that actually works and change a variable called isSignedIn, then the navigationKey of the stack group should remove from the stackcontainer the Login and Registration Screens when isSignedIn is equal to 'user' and no more 'guest', but this doesn't happen.
This is the code I use:
This updates the isSignedIn correctly
onAuthStateChanged(authApp, (user) => {
if (user) {
isSignedIn = 'user'
console.log(isSignedIn)
} else {
isSignedIn = 'guest'
console.log(isSignedIn)
}
});
This doesn't works at all
<NavigationContainer>
<Stack.Navigator>
<Stack.Group navigationKey={isSignedIn ? 'user' : 'guest'}>
{/* <Stack.Group> */}
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</Stack.Group>
<Stack.Group>
<Stack.Screen name="Home" component={HomeScreen} options={{headerBackVisible:false}}/>
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
I have no errors

I solved by removing the navigation key and changing my code as this:
const[userLogged,setUserLogged]= useState(false)
onAuthStateChanged(authApp, async (user) => {
if (user) {
setUserLogged(true)
} else {
setUserLogged(false)
}
});
then in StackNavigator:
{userLogged ? null : (
<Stack.Group>
<Stack.Screen name="Login" component={LoginScreen} options={{headerBackVisible:false}}/>
<Stack.Screen name="Registration" component={RegistrationScreen} options={{headerBackVisible:true}}/>
</Stack.Group>
)}

Related

Error in Rest Parameter in Fetcher Function SWR

So here I am developing a web app. I use supabase as the database and SWR as the React Hooks. I have followed the step by step on YouTube, but then I encountered the following problem. In the index.tsx file there is an error regarding the rest parameter in the following fetcher function, even though the function is a template function provided by SWR. The error says, "Rest parameter 'args' implicitly has an 'any[]' type." .How should I fix it?
const Home: NextPage = () => {
const [myPosts, setMyPosts] = useState([])
const fetcher = (...args) => fetch(...args).then(res => res.json())
const {data, error} = useSWR('/api/get-posts', fetcher, {refreshInterval: 200})
console.log(data)
useEffect(() => {
if (!data) return
setMyPosts(data.data)
}, [data])
return (
<div className={style.wrapper}>
<Header />
<Banner />
<main className={style.main}>
<div className={style.content}>
<CreatePost />
<Feed posts={myPosts}/>
</div>
<div className={style.infoContainer}>
<About />
</div>
</main>
</div>
)
}
export default Home
I hope that my data in database can be fetched and rendered in my Next.js project.

How to implement auto-login of users with firebase authentication and Expo?

I am trying to implement auto-login using firebase authentication and React Native (Expo).
I scoured through various documentation and all kinds of methods like onAuthStateChanged() and using Async Storage but I can't get any of them to work.
My current App.js is given below and I use classes on my screens rather than functions. Help is appreciated, please!
import { View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import LoginScreen from "./screens/LoginScreen";
import HomeScreen from "./screens/HomeScreen";
import RedeemScreen from "./screens/RedeemScreen";
import BlogScreen from "./screens/BlogScreen";
const Stack = createNativeStackNavigator();
export default function App() {
return (
<View style={{ flex: 1, backgroundColor: "#070707" }}>
<NavigationContainer>
<Stack.Navigator initialRouteName={"Login"}>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Blog"
component={BlogScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Redeem"
component={RedeemScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
</View>
);
}

Can someone please show me how to add an image/file upload to this code and then save it to the firebase firestore?

import React from 'react';
import {
SafeAreaView,
TextInput,
Button,
ActivityIndicator,
Text,
View,
} from 'react-native';
import {Formik} from 'formik';
import * as yup from 'yup';
import StyledInput from './styledInput';
import validationSchema from './validationSchema';
const ProductListingForm = () => (
<SafeAreaView style={{marginTop: 90}}>
<Formik
initialValues={{
listingTheme: '',
size: '',
barcode: '',
description: '',
units: '',
listingName: '',
quantity: '',
}}
onSubmit={(values, actions) => {
alert(JSON.stringify(values));
setTimeout(() => {
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={validationSchema}>
{formikProps => (
<React.Fragment>
<StyledInput
label={'Product Name'}
formikProps={formikProps}
formikKey="listingName"
placeholderText={'Enter Product Name'}
autoFocus
/>
<StyledInput
label={'Product Theme'}
formikProps={formikProps}
formikKey="listingTheme"
placeholderText={'Enter a theme that describes your product'}
/>
<StyledInput
label={'Barcode'}
formikProps={formikProps}
formikKey="barcode"
placeholderText={'Scan/Enter Barcode'}
/>
<StyledInput
label={'Size'}
formikProps={formikProps}
formikKey="size"
placeholderText={'Enter Product Size'}
/>
<StyledInput
label={'Units'}
formikProps={formikProps}
formikKey="units"
placeholderText={'Enter Product Units'}
/>
<StyledInput
label={'Description'}
formikProps={formikProps}
formikKey="description"
placeholderText={'Describe your product'}
/>
{formikProps.isSubmitting ? (
<ActivityIndicator />
) : (
<Button title="Submit" onPress={formikProps.handleSubmit} />
)}
</React.Fragment>
)}
</Formik>
</SafeAreaView>
);
export default ProductListingForm;
Above is my product listing form I created using Formik. I would love to be able to add photos to this form as an array as well as saving the form data values so I can load them on a product listing card. If anyone knows how or has any guides on Formik and Firebase please help me. I just need a little guidance and then I can take it from there.

How to manually re-render component using react-hook-form when validation errors are updated

facing challenges making validation classes to reflect automatically on custom datepicker Flatpickr using React-Hook-Forms,
const { register, handleSubmit, errors, control } = useForm({
mode: 'onChange'
})
<FormGroup>
<Controller
name="dateControl"
control={control}
defaultValue={null}
rules={{ required: true }}
render={({ value, onChange }) => (
<Flatpickr
value={value}
onChange={onChange}
id="hf-picker"
options={{
altInput: true,
altFormat: 'F j, Y',
dateFormat: 'Y-m-d',
altInputClass: classnames(
'form-control flatpickr-input',
{
'is-invalid': errors.dateControl && true
}
)
}}
/>
)}
/>
</FormGroup>
After troubleshooting, I realize everything works except that component fails to re-render whenever the validation errors are updated by react-hooks-form, is there anyway I can force a manual re-render instead, thanks
I think this has nothing to do with RHF, but somehow the options prop of the <Flatpickr /> component isn't updated when the config changes.
I'm assuming your using the react-flatpickr package - what you could do is simply pass the key prop to this component and setting it to the errors object of that control. This will force a re-render every time the errors of that form control change.
const isNotEmpty = (array) => array?.length > 0 || "Required";
<Controller
name="dateControl"
control={control}
defaultValue={null}
rules={{ validate: isNotEmpty }}
render={({ value, onChange }) => (
<>
<Flatpickr
key={errors.dateControl}
value={value}
onChange={onChange}
id="hf-picker"
options={{
altInput: true,
altFormat: "F j, Y",
dateFormat: "Y-m-d",
altInputClass: classnames("form-control flatpickr-input", {
"is-invalid": !!errors.dateControl
})
}}
/>
{errors.dateControl && <p>{errors.dateControl.message}</p>}
</>
)}
/>

MUI - Open datepicker when clicking anywhere in the TextField

I have a date picker that I want to show when the users click anywhere in the field not just on the calendar icon.
Here's the picker
export function DatePickerField(props) {
......
return (
<Grid container>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
{...field}
{...props}
disableToolbar
inputVariant="outlined"
value={selectedDate}
onChange={_onChange}
error={isError}
autoOk
invalidDateMessage={isError && error}
helperText={isError && error}
/>
</MuiPickersUtilsProvider>
</Grid>
);
}
I need to do this because if date entered manually, it throws no errors but I get invalid date in the form data.
How can show the picker when the field is clicked?
MUI v5 added the DatePicker component in the #mui/lab package. If you want a picker to be opened after when the user clicked inside the TextField, use MobileDatePicker, this doesn't have the calendar icon though, see this answer if you want to have one.
<MobileDatePicker
{...}
renderInput={(params) => <TextField {...params} />}
/>
The DesktopDatePicker however does have the calendar icon, but you have to write additional code to control the open state and tell the picker to open when TextField is clicked:
<DatePicker
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
renderInput={(params) => {
return (
<TextField
{...params}
onClick={(e) => setOpen(true)}
/>
);
}}
/>
Original Answer
You can control the KeyboardDatePicker's open state and set it to true when the TextField is clicked:
const [open, setOpen] = useState(false);
return (
<KeyboardDatePicker
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
TextFieldComponent={(props) => (
<TextField {...props} onClick={(e) => setOpen(true)} />
)}
{...other}
/>
);
Live Demo

Resources