Reject tx on component re-render - reactjs

I am making a webapp using react and ethers.js that works with metamask. If I call MyContract.MyFunc(xyz, function(error, result){ }); user will see a metamask popup. My code will get a response only if user presses SUBMIT or REJECT. But if the user refreshes the page without pressing either SUBMIT or REJECT, my code will never know the status of this transaction although the user is still able to submit this transaction.
The first part of my code sends a transaction and the second part posts info to my api. My issue is that the transaction part of the code produces a metamask popup for the user to confirm and sign the transaction. If the user continues with the transaction as expected my code work without problems. However, if the user refreshes the page or otherwise resets the state of my component after the metamask popup is produced and before they confirm it and then confirm it after the page reload, then I'm unable to post the data to my api and my app breaks. What can I do to stop this? Is there a way to reject transactions on page reloads or check if there unsigned transactions on metamask?
try {
const price = await connectedContract.getMintPrice();
const transaction = await connectedContract.primeMint({
value: price,
});
const receipt = await transaction.wait();
blockNumber = receipt.blockNumber;
} catch (err) {
console.error(err);
setState({ ...state, button: false });
}
axios
.post("http://localhost:5000/api/mints", {
_id: _address,
blockNumber: blockNumber,
})
.then(() => {
setState({
status: "Loading",
blockNumber: blockNumber,
button: false,
});
})
.catch((err) => {
console.error(err);
setState({ ...state, button: false });
});

Related

loss of connection is not causing an error in firestore client side?

I am trying to do a double action in my dispatch function. One action will update the current react state ! the other will update database I don't want to update my react state if the update to firestore fails for some reason, this thing works well if the database reject your call for some reason, but the issue lies in if I simply turn off Wi-Fi the try/catch or .catch doesn't seem to notice any error.
How to handle this ?
my current implementation is update state first then if the update fails I do a step back since I don't want to wait for the await making my app slow , so i update local state then update database and if any thing errors out I return state to default any idea how to handle this and why the loss of connection is not causing any error.
const AddData = async () => {
const payload = {//some pay load };
const docData = doc(collectionRef, clientId);
dispatch({
type: types.ADD_DATA,
payload: {
data: payload,
},
});
await updateDoc(docData, {
data: payload,
// not catching !
}).catch((err) => {
alert('Step BACK');
});
// not catching !
try {
} catch (error) {
alert('Module ExcercsiesState m Location Add routine');
errorHandeling(error, 'An error has happened', reduxDispatch, SetSnackBarMsg);
}
};

Firestore takes a long time to save data upon signing up and nothing happens after that

So I'm trying to save the user's information when they create an account into Firestore and this is my AuthContext.js
function signUp(user){
return auth.createUserWithEmailAndPassword(user.email,user.password)
.then(async res => {
await updateTeacherDatabase(res.user.uid, user)
})
.catch(error => console.log(error))
}
the auth variable is from firebase.js:
const app = firebase.initializeApp({...})
export const auth = app.auth(); //authentication
this is the updateTeacherDatabase function:
function updateTeacherDatabase(userID, user){
return db.collection('teacher-info').doc(userID).set({
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
role: 'teacher'
}).catch(error => console.log(error))
}
When the user creates and account and they submits the form, it should redirect them to the home page if there's no error. However, mine just stays on the sign up page for a really long time. My submit button is grey out to indicate that the form is sending data to the back end.
I checked my firestore Auth, the user is created but not the document in teacher-info collection. When I commented out the .then part, everything works as usual, or when I deleted the async await, it worked but the database is not updated. My console.log is clear, there's no error so I really don't know how to fix this issue?

Resetting multiple react Context API states at ones instead of creating resting action for each of them?

I have about 5 separate context api states that I want to rest after logging out from app, since they casing lots of issues any idea how to rest them redirecting doesn't seem to be doing much, and I don't want to refresh, this issue is my log out function will logout the user from server and simply redirect to main page but the state is still in the memory ?
const SignOut = () => {
signOut(auth)
.then(() => {
// Sign-out successful.
})
.catch((error) => {
// An error happened.
const errorCode = error.code;
const errorMessage = error.message;
snackbar.Msg(error, 'A signout error has happened.');
});
history.push('/');
};

Firebase sendPasswordResetEmail in JS SDK, doesn't send confirmation code

I am trying to do the following:
User asks to reset his password
Email is sent with a CODE and an URL to visit to reset his password
User visits the URL inputs the code and the new password and I call the confirmPasswordReset
But this doesn't work, the docs, their examples and also their functionality differs. Here's what happens
Greeting,
Follow this link to reset the example#gmail.com account password for the Example Dev app.
the URL
No Code, nothing, if I follow the URL it will take me to Firebase hosted app that will handle the reset with an ugly looking UI and THEN redirect me to the specified URL in the settings for sendResetEmail...
While the docs specify expected behavior, it differs from the actual one.
Sends a password reset email to the given email address.
#remarks
To complete the password reset, call confirmPasswordReset with the code supplied in the email sent to the user, along with the new password specified by the user.
#example
const actionCodeSettings = {
url: 'https://www.example.com/?email=user#example.com',
iOS: {
bundleId: 'com.example.ios'
},
android: {
packageName: 'com.example.android',
installApp: true,
minimumVersion: '12'
},
handleCodeInApp: true
};
await sendPasswordResetEmail(auth, 'user#example.com', actionCodeSettings);
// Obtain code from user.
await confirmPasswordReset('user#example.com', code);
The docs specify my intended behavior, but when used, it's totally different. What is happening here?
const onSubmit = (data: PasswordResetData) => {
setIsLoading(true);
sendPasswordResetEmail(getAuth(), data.email, {
url: "http://localhost:3002/en/auth/reset/confirm?email=" + data.email,
handleCodeInApp: true,
})
.then(() => {
})
.catch((err) => {
console.error(err);
})
.finally(() => {
setIsLoading(false);
});
};

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.

Resources