Skip to content

Commit df731a3

Browse files
authored
Merge pull request #126 from CreateThrive/refactor/fetch-user
Refactor: Fetch user
2 parents 748af9a + 5d657b7 commit df731a3

File tree

10 files changed

+274
-231
lines changed

10 files changed

+274
-231
lines changed

src/components/UserForm/UserForm.test.js

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,82 +16,73 @@ describe('<UserForm /> rendering', () => {
1616
file: null,
1717
id: 'test id',
1818
logoUrl: 'some logoUrl',
19-
createdAt: new Date().toDateString()
19+
createdAt: new Date().toDateString(),
2020
};
2121
});
2222

2323
it('should render without crashing', () => {
2424
const user = { ...userData, createdAt: '11/21/2020' };
2525

2626
const { component } = shallowWithProviders(
27-
<UserForm userData={user} action={actions.createUser} />
27+
<UserForm user={user} action={actions.createUser} />
2828
)({
29-
users: {}
29+
users: {},
3030
});
3131

3232
expect(component).toMatchSnapshot();
3333
});
3434

3535
it('should display user name preview', () => {
3636
const { component } = mountWithProviders(
37-
<UserForm userData={userData} action={actions.createUser} />
37+
<UserForm user={userData} action={actions.createUser} />
3838
)({
39-
users: {}
39+
users: {},
4040
});
4141

42-
expect(
43-
component
44-
.find('input.input.is-static')
45-
.at(1)
46-
.props().value
47-
).toEqual('Mateo');
42+
expect(component.find('input.input.is-static').at(1).props().value).toEqual(
43+
'Mateo'
44+
);
4845
});
4946

5047
it('should display email preview if it is creating a new user', () => {
5148
const { component } = mountWithProviders(
52-
<UserForm userData={userData} action={actions.createUser} />
49+
<UserForm user={userData} action={actions.createUser} />
5350
)({
54-
users: {}
51+
users: {},
5552
});
5653

5754
expect(
58-
component
59-
.find('input.input.is-static')
60-
.first()
61-
.props().value
55+
component.find('input.input.is-static').first().props().value
6256
).toEqual('mkrukuy@gmail.com');
6357
});
6458

6559
it('should display location preview', () => {
6660
const { component } = mountWithProviders(
67-
<UserForm userData={userData} isEditing action={actions.createUser} />
61+
<UserForm user={userData} isEditing action={actions.createUser} />
6862
)({
69-
users: {}
63+
users: {},
7064
});
7165

72-
expect(
73-
component
74-
.find('input.input.is-static')
75-
.at(2)
76-
.props().value
77-
).toEqual('Montevideo, Uruguay');
66+
expect(component.find('input.input.is-static').at(2).props().value).toEqual(
67+
'Montevideo, Uruguay'
68+
);
7869
});
7970

8071
it('should display admin preview', () => {
8172
const { component } = mountWithProviders(
82-
<UserForm userData={userData} isEditing action={actions.createUser} />
73+
<UserForm user={userData} isEditing action={actions.createUser} />
8374
)({
84-
users: {}
75+
users: {},
8576
});
8677

8778
expect(component.exists('.icon')).toBeTruthy();
8879
});
8980

9081
it('should display created preview', () => {
9182
const { component } = mountWithProviders(
92-
<UserForm userData={userData} isEditing action={actions.createUser} />
83+
<UserForm user={userData} isEditing action={actions.createUser} />
9384
)({
94-
users: {}
85+
users: {},
9586
});
9687
expect(component.find('p.date')).toBeTruthy();
9788
});
@@ -115,15 +106,15 @@ describe('<LoginForm /> actions', () => {
115106
logoUrl: 'some logoUrl',
116107
isAdmin: false,
117108
file: null,
118-
createdAt: new Date().toDateString()
109+
createdAt: new Date().toDateString(),
119110
};
120111
});
121112

122113
it('should dispatch createUser action when creating a new user', () => {
123114
const { component } = mountWithProviders(
124-
<UserForm userData={userData} action={actions.createUser} />
115+
<UserForm user={userData} action={actions.createUser} />
125116
)({
126-
users: {}
117+
users: {},
127118
});
128119

129120
component.find('form').simulate('submit');
@@ -133,9 +124,9 @@ describe('<LoginForm /> actions', () => {
133124

134125
it('should dispatch modifyUser action when editing a user', () => {
135126
const { component } = mountWithProviders(
136-
<UserForm userData={userData} isEditing action={actions.modifyUser} />
127+
<UserForm user={userData} isEditing action={actions.modifyUser} />
137128
)({
138-
users: {}
129+
users: {},
139130
});
140131

141132
component.find('form').simulate('submit');

src/components/UserForm/__snapshots__/UserForm.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ exports[`<UserForm /> rendering should render without crashing 1`] = `
143143
>
144144
<UserForm
145145
action={[Function]}
146-
userData={
146+
user={
147147
Object {
148148
"createdAt": "11/21/2020",
149149
"email": "mkrukuy@gmail.com",

src/components/UserForm/index.jsx

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable jsx-a11y/label-has-associated-control */
2-
import React, { useState, useEffect } from 'react';
2+
import React, { useEffect } from 'react';
33
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
44
import PropTypes from 'prop-types';
55
import { Link } from 'react-router-dom';
@@ -11,10 +11,10 @@ import { validateEmail } from 'utils';
1111
import './UserForm.scss';
1212
import DatePicker from '../DatePicker';
1313

14-
const UserForm = ({ isEditing, isProfile, userData, action }) => {
14+
const UserForm = ({ isEditing, isProfile, user, setUser, action }) => {
1515
const { loading } = useSelector(
16-
state => ({
17-
loading: state.users.loading
16+
(state) => ({
17+
loading: state.users.loading,
1818
}),
1919
shallowEqual
2020
);
@@ -25,16 +25,14 @@ const UserForm = ({ isEditing, isProfile, userData, action }) => {
2525
return () => dispatch(usersCleanUp());
2626
}, [dispatch]);
2727

28-
const [user, setUser] = useState(userData);
29-
3028
const onChangeHandler = useChangeHandler(setUser);
3129

32-
const onFileChangedHandler = event => {
30+
const onFileChangedHandler = (event) => {
3331
const file = event.target.files[0];
34-
setUser(prevState => ({ ...prevState, file, logoUrl: null }));
32+
setUser((prevState) => ({ ...prevState, file, logoUrl: null }));
3533
};
3634

37-
const onSubmitHandler = event => {
35+
const onSubmitHandler = (event) => {
3836
event.preventDefault();
3937
dispatch(
4038
action({ ...user, createdAt: user.createdAt, isEditing, isProfile })
@@ -43,7 +41,7 @@ const UserForm = ({ isEditing, isProfile, userData, action }) => {
4341

4442
let emailInput = {
4543
modifier: null,
46-
message: { modifier: null, content: null }
44+
message: { modifier: null, content: null },
4745
};
4846

4947
const invalidEmail = user.email && !validateEmail(user.email);
@@ -55,8 +53,8 @@ const UserForm = ({ isEditing, isProfile, userData, action }) => {
5553
modifier: 'is-danger',
5654
message: {
5755
modifier: 'is-danger',
58-
content: invalidEmailMessage
59-
}
56+
content: invalidEmailMessage,
57+
},
6058
};
6159
}
6260

@@ -270,8 +268,9 @@ const UserForm = ({ isEditing, isProfile, userData, action }) => {
270268
<div className="control">
271269
<button
272270
type="submit"
273-
className={`button is-primary ${loading &&
274-
'is-loading'}`}
271+
className={`button is-primary ${
272+
loading && 'is-loading'
273+
}`}
275274
disabled={!canSubmit}
276275
>
277276
<span>{useFormatMessage('UserForm.submit')}</span>
@@ -383,7 +382,7 @@ const UserForm = ({ isEditing, isProfile, userData, action }) => {
383382
weekday: 'short',
384383
year: 'numeric',
385384
month: 'short',
386-
day: 'numeric'
385+
day: 'numeric',
387386
})}
388387
</p>
389388
</div>
@@ -402,11 +401,11 @@ UserForm.propTypes = {
402401
id: PropTypes.string,
403402
isAdmin: PropTypes.bool.isRequired,
404403
name: PropTypes.string.isRequired,
405-
location: PropTypes.string.isRequired,
404+
location: PropTypes.string,
406405
logoUrl: PropTypes.string,
407-
createdAt: PropTypes.string.isRequired
406+
createdAt: PropTypes.string.isRequired,
408407
}),
409-
action: PropTypes.func.isRequired
408+
action: PropTypes.func.isRequired,
410409
};
411410

412411
export default UserForm;

src/pages/User/User.test.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,52 @@ import User from '.';
66

77
describe('<User /> rendering', () => {
88
it('should render without crashing', () => {
9-
const { component } = shallowWithProviders(<User />)({ users: {} });
9+
const { component } = shallowWithProviders(<User />)({
10+
users: {
11+
user: {
12+
name: '',
13+
email: '',
14+
location: '',
15+
isAdmin: false,
16+
file: null,
17+
createdAt: new Date().toDateString(),
18+
},
19+
},
20+
});
1021

1122
expect(component).toMatchSnapshot();
1223
});
1324

1425
it('should not show the spinner when creating a user', () => {
15-
const { component } = mountWithProviders(<User />)({ users: {} });
26+
const { component } = mountWithProviders(<User />)({
27+
users: {
28+
user: {
29+
name: '',
30+
email: '',
31+
location: '',
32+
isAdmin: false,
33+
file: null,
34+
createdAt: new Date().toDateString(),
35+
},
36+
},
37+
});
1638

1739
expect(component.exists(ClipLoader)).toBeFalsy();
1840
});
1941

2042
it('should render the UserForm component when creating a user', () => {
21-
const { component } = mountWithProviders(<User />)({ users: {} });
43+
const { component } = mountWithProviders(<User />)({
44+
users: {
45+
user: {
46+
name: '',
47+
email: '',
48+
location: '',
49+
isAdmin: false,
50+
file: null,
51+
createdAt: new Date().toDateString(),
52+
},
53+
},
54+
});
2255

2356
expect(component.exists(UserForm)).toBeTruthy();
2457
});

src/pages/User/index.jsx

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,60 @@
11
import React, { useState, useEffect } from 'react';
22
import { useParams, Redirect } from 'react-router-dom';
3-
import { useSelector, shallowEqual } from 'react-redux';
3+
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
44
import ClipLoader from 'react-spinners/ClipLoader';
55

66
import UserForm from 'components/UserForm';
7-
import { createUser, modifyUser } from 'state/actions/users';
7+
import { createUser, modifyUser, fetchUsers } from 'state/actions/users';
88
import paths from 'pages/Router/paths';
9-
import firebase from 'firebase.js';
109
import { useFormatMessage } from 'hooks';
1110

1211
const User = () => {
1312
const { id } = useParams();
1413

15-
const { success } = useSelector(
16-
state => ({
17-
success: state.users.success
14+
const { success, usersList, userData, error } = useSelector(
15+
(state) => ({
16+
success: state.users.success,
17+
usersList: state.users.list,
18+
userData: state.users.user,
19+
error: state.users.error,
1820
}),
1921
shallowEqual
2022
);
2123

22-
const [user, setUser] = useState({
23-
name: '',
24-
email: '',
25-
location: '',
26-
isAdmin: false,
27-
file: null,
28-
createdAt: new Date().toDateString()
29-
});
24+
const [user, setUser] = useState(userData || {});
3025

31-
useEffect(() => {
32-
const fetchUserData = async () => {
33-
const response = (
34-
await firebase
35-
.database()
36-
.ref(`users/${id}`)
37-
.once('value')
38-
).val();
39-
return response;
40-
};
26+
const dispatch = useDispatch();
4127

28+
useEffect(() => {
4229
if (id) {
43-
fetchUserData()
44-
.then(userData => {
45-
setUser({
46-
...userData,
47-
createdAt: userData.createdAt,
48-
id,
49-
isAdmin: userData.isAdmin
50-
});
51-
})
52-
.catch(() => {
53-
setUser({ error: true });
54-
});
30+
const userFetched = usersList.find(
31+
(fetchedUser) => fetchedUser.id === id
32+
);
33+
if (userFetched) {
34+
setUser(userFetched);
35+
} else if (userData.id === id) {
36+
setUser(userData);
37+
} else {
38+
dispatch(fetchUsers(id));
39+
}
5540
}
56-
}, [id]);
41+
}, [id, userData]);
5742

5843
const isEditing = !!id;
5944

6045
const userForm =
61-
!user.name && id ? (
46+
!user && id ? (
6247
<ClipLoader />
6348
) : (
6449
<UserForm
6550
isEditing={isEditing}
66-
userData={user}
51+
user={user}
52+
setUser={setUser}
6753
action={isEditing ? modifyUser : createUser}
6854
/>
6955
);
7056

71-
const redirect = (user.error || success) && <Redirect to={paths.USERS} />;
57+
const redirect = (error || success) && <Redirect to={paths.USERS} />;
7258

7359
const editUserMessage = useFormatMessage('User.editUser');
7460

0 commit comments

Comments
 (0)