Skip to content

Commit 7b418c6

Browse files
committed
Refactor react-hook-form
1 parent 3eab227 commit 7b418c6

File tree

11 files changed

+144
-94
lines changed

11 files changed

+144
-94
lines changed

src/components/UserForm/index.jsx

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { Link } from 'react-router-dom';
66
import { useForm, Controller } from 'react-hook-form';
77
import classNames from 'classnames';
88
import { yupResolver } from '@hookform/resolvers';
9-
import * as yup from 'yup';
109

1110
import paths from 'pages/Router/paths';
1211
import { usersCleanUp } from 'state/actions/users';
@@ -16,7 +15,7 @@ import ErrorMessage from 'components/ErrorMessage';
1615

1716
import './UserForm.scss';
1817

19-
const UserForm = ({ isEditing, isProfile, user, setUser, action }) => {
18+
const UserForm = ({ isEditing, isProfile, user, onSubmitHandler, schema }) => {
2019
const { loading, success } = useSelector(
2120
(state) => ({
2221
loading: state.users.loading,
@@ -27,38 +26,18 @@ const UserForm = ({ isEditing, isProfile, user, setUser, action }) => {
2726

2827
const dispatch = useDispatch();
2928

30-
const schema = yup.object().shape({
31-
email: isEditing
32-
? yup.string().email().notRequired()
33-
: yup.string().email().required(),
34-
name: yup.string().required(),
35-
isAdmin: yup.boolean().notRequired(),
36-
location: yup.string().notRequired(),
37-
createdAt: yup.string().required(),
38-
});
39-
40-
const { register, handleSubmit, errors, control, watch } = useForm({
29+
const { register, handleSubmit, errors, control, watch, setValue } = useForm({
4130
defaultValues: { ...user },
4231
resolver: yupResolver(schema),
4332
});
4433

4534
useEffect(() => {
4635
if (success) {
47-
setUser((prevState) => ({ ...prevState, file: null }));
36+
setValue('file', null);
4837
}
4938
return () => dispatch(usersCleanUp());
5039
}, [dispatch, success]);
5140

52-
const onSubmitHandler = (value) => {
53-
const newUser = {
54-
...value,
55-
file: value?.file[0] || null,
56-
isEditing,
57-
isProfile,
58-
};
59-
dispatch(action(newUser));
60-
};
61-
6241
const invalidEmailMessage = useFormatMessage('UserForm.invalidEmail');
6342

6443
const imagePreviewUrl =
@@ -102,7 +81,8 @@ const UserForm = ({ isEditing, isProfile, user, setUser, action }) => {
10281
type="text"
10382
readOnly="readOnly"
10483
className="input is-static"
105-
value={user.email}
84+
name="email"
85+
ref={register}
10686
/>
10787
</div>
10888
</div>
@@ -421,7 +401,9 @@ UserForm.propTypes = {
421401
createdAt: PropTypes.string.isRequired,
422402
email: PropTypes.string.isRequired,
423403
}).isRequired,
424-
action: PropTypes.func.isRequired,
404+
onSubmitHandler: PropTypes.func.isRequired,
405+
// eslint-disable-next-line react/forbid-prop-types
406+
schema: PropTypes.object.isRequired,
425407
isEditing: PropTypes.bool,
426408
isProfile: PropTypes.bool,
427409
};

src/languages/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"Login.safePassword": "Safe password",
1414
"Login.unsafePassword": "Unsafe password",
1515
"Login.invalidEmail": "Invalid email",
16+
"Login.invalidPassword": "Invalid password",
1617
"NotFound.404": "Error 404: page not found",
1718
"NotFound.url": "The requested URL {url} was not found",
1819
"NotFound.back": "Go Back",
@@ -27,6 +28,7 @@
2728
"ChangePassword.insecurePassword": "Insecure password",
2829
"ChangePassword.matchPassword": "Passwords match",
2930
"ChangePassword.notMatchPassword": "Passwords do not match",
31+
"ChangePassword.invalidPassword": "Password must be at least six characters long",
3032
"Section.section": "Section",
3133
"Section.content": "Section content",
3234
"ResetPassword.recovery": "Password Recovery",

src/languages/es.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"Login.safePassword": "Contraseña segura",
1414
"Login.unsafePassword": "Contraseña insegura",
1515
"Login.invalidEmail": "Email inválido",
16+
"Login.invalidPassword": "Contraseña inválida",
1617
"NotFound.404": "Error 404: página no encontrada",
1718
"NotFound.url": "El URL {url} no fue encontrado",
1819
"NotFound.back": "Regresar",
@@ -27,6 +28,7 @@
2728
"ChangePassword.insecurePassword": "Contraseña Insegura",
2829
"ChangePassword.matchPassword": "Contraseñas coinciden",
2930
"ChangePassword.notMatchPassword": "Contraseñas no coinciden",
31+
"ChangePassword.invalidPassword": "La contraseña debe tener al menos seis caracteres de largo",
3032
"Section.section": "Sección",
3133
"Section.content": "Contenido de la Sección",
3234
"ResetPassword.recovery": "Recuperar Contraseña",
@@ -74,7 +76,7 @@
7476
"UserForm.goBack": "Regresar",
7577
"UserForm.userPreview": "Vista previa del usuario",
7678
"auth/email-already-exists": "Email ya esta siendo usado",
77-
"auth/invalid-email": "El Email inválido",
79+
"auth/invalid-email": "Email inválido",
7880
"auth/wrong-password": "Credenciales inválidas",
7981
"auth/user-disabled": "Usuario deshabilitado",
8082
"auth/too-many-requests": "Demasiados intentos, intententelo más tarde",

src/pages/Login/index.jsx

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-nested-ternary */
12
import React, { useEffect } from 'react';
23
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
34
import { Redirect, Link } from 'react-router-dom';
@@ -97,6 +98,8 @@ const Login = () => {
9798

9899
const forgotPasswordMessage = useFormatMessage('Login.forgotPassword');
99100

101+
const invalidPasswordMessage = useFormatMessage('Login.invalidPassword');
102+
100103
return (
101104
<section className="section hero is-fullheight is-error-section">
102105
{redirect}
@@ -121,15 +124,9 @@ const Login = () => {
121124
<p className="label">{useFormatMessage('Login.email')}</p>
122125
<div className="control is-clearfix">
123126
<input
124-
className={classNames(
125-
'input',
126-
{
127-
'is-danger': errors.email,
128-
},
129-
{
130-
'is-success': !errors.email && isEmailLink,
131-
}
132-
)}
127+
className={classNames('input', {
128+
'is-danger': errors.email,
129+
})}
133130
name="email"
134131
ref={register}
135132
/>
@@ -150,25 +147,27 @@ const Login = () => {
150147
'is-danger': errors.password,
151148
},
152149
{
153-
'is-success':
154-
isValidPassword &&
155-
!errors.password &&
156-
isEmailLink,
150+
'is-success': isEmailLink && isValidPassword,
157151
}
158152
)}
159153
type="password"
160154
name="password"
161155
ref={register}
162156
/>
163157
</div>
164-
{isEmailLink &&
165-
(errors.password ? (
158+
{isEmailLink ? (
159+
errors.password ? (
166160
<ErrorMessage text={unsafePasswordMessage} />
167161
) : (
168162
isValidPassword && (
169-
<ErrorMessage text={safePasswordMessage} />
163+
<p className="is-success">{safePasswordMessage}</p>
170164
)
171-
))}
165+
)
166+
) : (
167+
errors.password && (
168+
<ErrorMessage text={invalidPasswordMessage} />
169+
)
170+
)}
172171
</div>
173172
<br />
174173
<div className="field is-grouped">
@@ -204,22 +203,26 @@ const Login = () => {
204203
</p>
205204
)}
206205
</form>
207-
<hr />
208-
<div
209-
className={classNames(
210-
'field',
211-
'is-grouped',
212-
classes.socialButtons
213-
)}
214-
>
215-
<StyledFirebaseAuth
216-
uiConfig={uiConfig(
217-
onSignInSuccessHandler,
218-
onSignInFailHandler
219-
)}
220-
firebaseAuth={firebase.auth()}
221-
/>
222-
</div>
206+
{!isEmailLink && (
207+
<>
208+
<hr />
209+
<div
210+
className={classNames(
211+
'field',
212+
'is-grouped',
213+
classes.socialButtons
214+
)}
215+
>
216+
<StyledFirebaseAuth
217+
uiConfig={uiConfig(
218+
onSignInSuccessHandler,
219+
onSignInFailHandler
220+
)}
221+
firebaseAuth={firebase.auth()}
222+
/>
223+
</div>
224+
</>
225+
)}
223226
</div>
224227
</div>
225228
</div>

src/pages/Profile/ChangePassword/index.jsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@ const schema = yup.object().shape({
2424
});
2525

2626
const ChangePasswordCard = () => {
27-
const { loading } = useSelector(
27+
const { loading, changedPassword } = useSelector(
2828
(state) => ({
2929
loading: state.auth.loading,
30+
changedPassword: state.auth.changedPassword,
3031
}),
3132
shallowEqual
3233
);
3334

3435
const dispatch = useDispatch();
3536

36-
const { register, handleSubmit, watch } = useForm({
37+
const { register, handleSubmit, watch, setValue, errors } = useForm({
3738
defaultValues: {
3839
current: '',
3940
new: '',
@@ -43,15 +44,27 @@ const ChangePasswordCard = () => {
4344
});
4445

4546
useEffect(() => {
47+
if (changedPassword) {
48+
setValue('current', '');
49+
setValue('new', '');
50+
setValue('confirmation', '');
51+
}
4652
return () => dispatch(authCleanUp());
47-
}, [dispatch]);
53+
}, [dispatch, changedPassword]);
4854

4955
const newPassword = watch('new');
5056
const currentPassword = watch('current');
5157
const confirmationPassword = watch('confirmation');
5258

5359
const isNewPasswordSecure = newPassword && newPassword.length >= 6;
5460

61+
const isCurrentPasswordInvalid =
62+
currentPassword && currentPassword.length < 6;
63+
64+
const invalidPasswordMessage = useFormatMessage(
65+
`ChangePassword.invalidPassword`
66+
);
67+
5568
const safePasswordMessage = useFormatMessage(`ChangePassword.safePassword`);
5669

5770
const insecurePasswordMessage = useFormatMessage(
@@ -107,14 +120,17 @@ const ChangePasswordCard = () => {
107120
<div className="control">
108121
<input
109122
className={classNames('input', {
110-
'is-danger':
111-
currentPassword && currentPassword.length < 6,
123+
'is-danger': isCurrentPasswordInvalid,
112124
})}
113125
type="password"
114126
name="current"
115127
ref={register}
116128
/>
117129
</div>
130+
{isCurrentPasswordInvalid ||
131+
(errors.current && (
132+
<ErrorMessage text={invalidPasswordMessage} />
133+
))}
118134
</div>
119135
</div>
120136
</div>

src/pages/Profile/__snapshots__/Profile.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ exports[`<Profile /> rendering should render without crashing 1`] = `
7070
>
7171
<input
7272
class="input is-static"
73+
name="email"
7374
readonly=""
7475
type="text"
75-
value="test@test.com"
7676
/>
7777
</div>
7878
</div>

src/pages/Profile/index.jsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import React from 'react';
2-
import { useSelector, shallowEqual } from 'react-redux';
2+
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
3+
import * as yup from 'yup';
34

45
import { useFormatMessage } from 'hooks';
56
import UserForm from 'components/UserForm';
67
import { modifyUser } from 'state/actions/users';
78
import ChangePassword from './ChangePassword';
89

10+
const schema = yup.object().shape({
11+
name: yup.string().required(),
12+
isAdmin: yup.boolean().notRequired(),
13+
location: yup.string().notRequired(),
14+
createdAt: yup.string().required(),
15+
});
16+
917
const Profile = () => {
1018
const { userData } = useSelector(
1119
(state) => ({
@@ -14,6 +22,19 @@ const Profile = () => {
1422
shallowEqual
1523
);
1624

25+
const dispatch = useDispatch();
26+
27+
const onSubmitHandler = (value) => {
28+
const newUser = {
29+
...value,
30+
file: value?.file[0] || null,
31+
isEditing: true,
32+
isProfile: true,
33+
id: userData.id,
34+
};
35+
dispatch(modifyUser(newUser));
36+
};
37+
1738
return (
1839
<>
1940
<section className="hero is-hero-bar">
@@ -22,7 +43,13 @@ const Profile = () => {
2243
</div>
2344
</section>
2445
<section className="section is-main-section">
25-
<UserForm isEditing isProfile user={userData} action={modifyUser} />
46+
<UserForm
47+
isEditing
48+
isProfile
49+
user={userData}
50+
onSubmitHandler={onSubmitHandler}
51+
schema={schema}
52+
/>
2653
<ChangePassword />
2754
</section>
2855
</>

src/pages/User/__snapshots__/User.test.js.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ exports[`<User /> rendering should render without crashing 1`] = `
204204
<input
205205
class=""
206206
type="text"
207-
value="09-24-20"
207+
value="09-25-20"
208208
/>
209209
</div>
210210
</div>
@@ -429,7 +429,7 @@ exports[`<User /> rendering should render without crashing 1`] = `
429429
<p
430430
class="date"
431431
>
432-
Thu, Sep 24, 2020
432+
Fri, Sep 25, 2020
433433
</p>
434434
</div>
435435
</div>

0 commit comments

Comments
 (0)