React native firebase phone authentication, if code sent navigate to otp screen - reactjs

I am using react native firebase, if code sent then i want to navigate to otp screen
But it shows an warning :
Non-serializable values were found in the navigation state. Check:
OtpVerification > params.confirm._auth._app._deleteApp (Function)
This can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions'
My code :
In login Screen :
async function signInWithPhoneNumber(phoneNumber) {
try {
const confirmation = await auth().signInWithPhoneNumber(phoneNumber);
props.navigation.navigate('OtpVerification', {
confirm: confirmation,
phoneNo,
});
} catch (error) {
console.log(error);
}
}
In Otp Screen :
async function confirmCode() {
if (otp) {
try {
await confirm.confirm(otp);
props.navigation.navigate('OnBoarding');
} catch (error) {
AlertMsg('Invalid OTP');
}
} else {
AlertMsg('Please Enter OTP');
}
}

So I believe in belive function where you have confirmation variable, You might have to pass some constant value over there handling the return of firebase signin.
async function signInWithPhoneNumber(phoneNumber) {
try {
const confirmation = await auth().signInWithPhoneNumber(phoneNumber);
props.navigation.navigate('OtpVerification', {
confirm: confirmation,
phoneNo,
});
} catch (error) {
console.log(error);
}
Check this document - https://reactnavigation.org/docs/troubleshooting/#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state
This expo for your navigation - https://snack.expo.dev/vKpugczaG

Related

Combine SvelteKit's throw Redirect with Felte's onSuccess

The problem:
Nothing happends when throwing throw redirect(302, '/auth/sign-up-success') in SvelteKit's actions if onSuccess: () => {...} is set in Felte's createForm({...}).
Example:
// +page.server.ts
export const actions: Actions = {
default: async (event) => {
...
throw redirect(302, '/auth/sign-up-success');
}
}
// SignUpForm.svelte
const { form, errors } = createForm({
onSuccess: (response) => {
invalidate('app:auth')
},
...
}
If I would delete the onSuccess part, then redirect would happend.
Question:
Is there a way to reuse that redirect form success response logic from default Felte form config without writing it again myself?
Action responses are JSON objects with a type, you could read the response and redirect on the client:
async onSuccess(response) {
const { type, location } = await response.json();
if (type == 'redirect') {
goto(location); // from '$app/navigation'
return;
}
}
I would not recommend using this library though. It appears to be incompatible with SSR and one of its main actions shares the name of the form data property used by SvelteKit form actions.
Depending on why you are using this, there might be more suitable tools for SvelteKit in particular (if you even need any, SvelteKit does many things out of the box).

Supabase reset password for email

Im try to reset password user for supabase in react but it says resetPasswordForEmail is undefined```
const { data, error } = await supabase.auth.api.resetPasswordForEmail(email)
if (data) {
console.log(data)
}
if (error) {
console.log(error)
}
}
I try to run the code but it gives and error because of an undefined function I expected to send an email
You're probably on v2, it should be:
supabase.auth.resetPasswordForEmail
Not:
supabase.auth.api.resetPasswordForEmail
For reference: https://supabase.com/docs/reference/javascript/auth-resetpasswordforemail
Check this out as well, it has some important notes you may need to know:
https://github.com/supabase/supabase/discussions/3360#discussioncomment-3947228

React login using context API with private route

In my react web app, login-logout functionality is implemented using context-API and hooks. Everything seems to work fine except for the fact that I have to click the 'Login' button twice to push the user to the dashboard.
The statement, return <Redirect to="/dashboard /> does not work, instead I have to use history.push('/dashboard'), which does not seems to be a better option to me while login.
Here is the working snippet :
https://codesandbox.io/s/wizardly-worker-mqkex?file=/src/AuthContext.js
Also, I need some suggestions for the best practise to fetch the logged user details in other components. Using localstorage or global context API state, which of them serves as the best option for the same ?
Any help to resolve this, appreciated :)
Well, it boils down to the simple fact that your context is not updated when you do your check. The simplest solution would be to remove the check for isLoggedIn and push the user to the Dashboard:
const postLogin = async (e) => {
e.preventDefault()
try {
await login()
props.history.push('/dashboard')
} catch (error) {
dispatch({
type: 'LOGIN_FAILURE',
payload: 'Unable to login'
})
}
}
Then throw an error in your login function when you don't get a 200 back:
const login = async () => {
const loginUser = { status: 200, id: '3654634565659abhdgh' }
if (loginUser.status === 200) {
dispatch({
type: 'LOGIN_SUCCESS',
payload: loginUser.id
})
} else {
throw new Error("Invalid Credentials")
}
}
As your login code is in a try catch block, the user won't get pushed to the Dashboard when the login fails.

Remember me with redux storage

I have userDetails in redux store and I used redux persist with redux storage to save the details after loads page or after closing my app.
The problem is, when I logged in and I don't checked the rememberMe in index.js is checked if !rememberMe and do logOut() right after login.
So I need to check just at the entrance into the app for the first time and if !rememberMe I will call logOut() but if userDetails !== 'emepty' && rememberMe I will do login() for get valid token.
Why I need to check this it in the first time? because I need to reset the uesrDetails to guest details if !rememberMe.
This is my index.js:
const setBeforeLists = useCallback(
(lists) => {
beforeListsChanged(lists);
},
[beforeListsChanged]
);
const setUserDetails = useCallback(
(userDetails) => {
userDetailsChanged(userDetails);
},
[userDetailsChanged]
);
useEffect(() => {
//userDetails.id === 'empty' is guest.
if (
userDetails.id !== 'empty' &&
!userDetails.rememberMe
) {
logOut(setUserDetails, setBeforeLists);
}
}, [
setBeforeLists,
setUserDetails,
userDetails
]);
When you refresh the app, the store will be reset. The token is gone. As we expected.
So, we can’t use the state to store the authentication token. This is where AsyncStorage comes onto the stage.
I'm replying to a react-native application.
If it's a web application use session storage.
Let’s import AsyncStorage in the React Native project:
import { AsyncStorage } from "react-native";
Then, let’s create two functions,setToken and getToken, for storing and retrieving the persistent data. These are the main methods of this tutorial. Here, we are storing and retrieving the user data from/to AsyncStorage.
async storeToken(user) {
try {
await AsyncStorage.setItem("userDetails", JSON.stringify(user));
} catch (error) {
console.log("Something went wrong", error);
}
}
async getToken(user) {
try {
let userDetails = await AsyncStorage.getItem("userDetails");
let data = JSON.parse(userDetails);
console.log(data);
} catch (error) {
console.log("Something went wrong", error);
}
}
componentDidMount() {
this.getToken();
}
Let’s prove it. The token is thereafter you quit & reopen the app. Try it out yourself. Now, our app automatically logs you in after each session.
Hope this helps!

React router 4 history push component re render

With redux-saga and react router 4. I am trying to implement a flow for user registration. I am focusing on the part where user is presented a registration screen on /user/register route.
GOAL
Goal is to update the status of user registration on this same screen as an Alert depending upon either the user created successfully or there already exists a user. I am using redux-saga and using history.push from saga to update the view.
PROBLEM
The alert is shown but only after I reload the /user/register page.
I am passing state to history.push from my saga and then in my component based on that state which I extract from this.props.location.state I prepare the content for alert.
Register Component
// Form submission handler
handleUserRegistration = user => {
this.props.registerUser(user, this.props.history);
}
// Prepring the alert content
getAlertUI = signupState => {
if (signupState.signupSuccess) {
return <UncontrolledAlert color='success'>{'Verification email sent. Please verify your account.'}</UncontrolledAlert>
}else {
return <UncontrolledAlert color='danger'>{signupState.error.message}</UncontrolledAlert>
}
}
render () {
let alertContent = null;
const signupResponse = this.props.location.state;
if (signupResponse) {
if (signupResponse.error) {
alertContent = this.getAlertUI({signupSuccess: false, error: signupResponse.error});
}else {
if (signupResponse.verificationEmailSent) {
alertContent = this.getAlertUI({signupSuccess: true})
}
}
}
return (
<div> {alertContent} </div>
// My form component goes here.
)
}
While is my saga. I am using history.push with the necessary information.
saga.js
const registerWithEmailPasswordAsync = async (userData) =>
await axios.post(apiUrls.SINGUP_USER, userData )
.then(response => {
return {
isError: false,
data: response.data,
}
})
.catch(error => {
return {
isError: true,
errorDetails: {
status: error.response ? error.response.status : null,
message: error.response ? error.response.data : null,
}
}
})
function* registerUser({ payload }) {
const { history } = payload;
try {
const registerUser = yield call(registerWithEmailPasswordAsync, payload.user);
if (!registerUser.isError) {
history.push('/user/register', {verificationEmailSent: true});
} else {
if (registerUser.errorDetails) {
history.push('/user/register', {error: registerUser.errorDetails} );
}
}
} catch (error) {
console.log('register error : ', error)
}
}
I am pretty new to this, Please share if this is the better approach or not? And if it is why isn't it updating my view. Any pointers are highly appreciated.
Don't use history.push just to update state
The only reason I could see you using history.push from within the saga is for sending the user to a dashboard/verification page after a successful sign up. There is no reason to use history.push just to pass some state to the component dynamically. Update your redux state by dispatching an action, not using history.push
You don't necessarily have to update state to notify the user of a sign-up error
You asked if your general approach was the best. Personally, I don't think it is. I wouldn't work that hard. Just use something like react-toastify. You can then just place a ToastContainer in your App component, then call toastify(successMessage/error)

Resources