This blog post originally posted on my blog site and you can find it here.
As I said in an earlier post we have to manage 2 scenarios here.
- Refresh the cache for forgot password
- Error handle for token errors.
Add below code lines to handle the token errors. We are using states here.
const [tokenError, setTokenError] = useState("");
Then we are adding the below code to check that token error exist. If so we are. adding it to state.
// take out toErrorMap first
const errorMap = toErrorMap(response.data.changePassword.errors);
if ("token" in errorMap) {
// this is because we defined filed as token in user.ts in backend
setTokenError(errorMap.token);
}
Let’s display this error.
{
tokenError ? <Box color="red">{tokenError}</Box> : null;
}
Add this moment if you try, you will get 404
error. The issue in here, that we didn't wrap this with withUrqlClient
. Let’s cover the component with it.
export default withUrqlClient(createUrqlClient)(ChangePassword);
Now, we need to delete the token from the back-end once we use this token. Let’s do that next.
// in resolvers/user.ts file
// first get the key out
const key = FORGET_PASSWORD_PREFIX + token;
const userId = await redis.get(key);
// then delete the key
await redis.del(key);
req.session.userId = user.id;
Now if you try to use the token 2nd time to change the password, you will get the token expired error. Cool. All working fine now.
Okay, now we only left here, if the token expired your need to get a new token. Let’s add that. First, we are adding a link to get a new token page.
// update code to below code block in [token].tsx file.
{
tokenError ? (
<Box>
<Box color="red">{tokenError}</Box>
<NextLink href="/forgot-password">
<Link>Click here to get a new token.</Link>
</NextLink>
</Box>
) : null;
}
Once you click on the link it will bring you to forgot-password
page. Let’s quickly add that page.
import React from "react";
const ForgotPassword: React.FC<{}> = ({}) => {
return <div>Forgot Password</div>;
};
export default ForgotPassword;
This also needs to add to Login
page.
// under to inputfield add this code
<Flex mt={2}>
<NextLink href="/forgot-password">
<Link ml="auto">forgot password?</Link>
</NextLink>
</Flex>
As the last for this forgot-passward
page, we need the user to insert an email address. Let’s copy from from Login
page and add it here. Also, we need to create a mutation for forgot-password
.This will only return a boolean value.
mutation ForgotPassword($email: String!) {
forgotPassword(email: $email)
}
In forgot-password.tsx
page, we use state
to set a success message.
const [complete, setComplete] = userState(false);
Here is the full code for forgot-password.tsx
file.
const [complete, setComplete] = userState(false);
const [, forgotPassword] = useForgotPasswordMutation();
return (
<Wrapper variant="small">
<Formik
initialValues={{ email: "" }}
onSubmit={async (values) => {
await forgotPassword(values);
setComplete(true);
}}
>
{({ isSubmitting }) =>
complete ? (
<Box>we sent a password reset link to your email. Please check.</Box>
) : (
<Form>
<InputField
name="email"
placeholder="email"
label="Email"
type="email"
/>
<Button
isLoading={isSubmitting}
mt={4}
type="submit"
colorScheme="teal"
>
Forgot Password
</Button>
</Form>
)
}
</Formik>
</Wrapper>
);
At this point, we have done almost everything with user management and authentication tasks of this application. From the next blog post, let’s work on adding posts to the Reddit clone.
Thanks for reading this. If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.
That’s for today friends. See you soon. Thank you.
References:
This article series based on the Ben Award - Fullstack React GraphQL TypeScript Tutorial. This is an amazing tutorial and I highly recommend you to check that out.
Main image credit
Top comments (0)