diff options
-rw-r--r-- | src/hooks/APIClient.ts | 17 | ||||
-rw-r--r-- | src/pages/ProfilePage/ProfileInfo.tsx | 9 | ||||
-rw-r--r-- | src/pages/ProfilePage/ProfilePage.tsx | 57 |
3 files changed, 40 insertions, 43 deletions
diff --git a/src/hooks/APIClient.ts b/src/hooks/APIClient.ts new file mode 100644 index 0000000..fa23a21 --- /dev/null +++ b/src/hooks/APIClient.ts @@ -0,0 +1,17 @@ +import useSWR from 'swr'; +import { get } from '../requests'; + + +const fetcher = (endpoint: string) => get(endpoint).then(response => response.data); + + +export const useUser = (username: string) => { + return useSWR( + `/users?username=${username}`, + (url: string) => get(url).then(response => response.data[0]) + ); +}; + +export const useProfile = (id: string) => { + return useSWR(id && `/profiles/${id}`, fetcher, { initialData: [] }); +}; diff --git a/src/pages/ProfilePage/ProfileInfo.tsx b/src/pages/ProfilePage/ProfileInfo.tsx index e4ef66a..8b1447a 100644 --- a/src/pages/ProfilePage/ProfileInfo.tsx +++ b/src/pages/ProfilePage/ProfileInfo.tsx @@ -16,7 +16,6 @@ interface PropTypes { totalVotes: number; userInfo: User | undefined; setUserInfo: (userInfo: User) => void; - isLoading: boolean; } const useStyles = makeStyles(theme => ({ @@ -83,7 +82,7 @@ const useStyles = makeStyles(theme => ({ const ProfileInfo: React.FC<PropTypes> = ({ - savedPolls, totalVotes, setUserInfo, userInfo, isLoading + savedPolls, totalVotes, setUserInfo, userInfo }) => { const classes = useStyles(); const [input, setInput] = useState(false); @@ -105,7 +104,7 @@ const ProfileInfo: React.FC<PropTypes> = ({ return ( <div className={classes.root}> { - isLoading + !userInfo ? <Skeleton animation="wave" variant="circle" width={150} height={150} className={classes.avatar} /> : userInfo?._id === localStorage.getItem('userId') ? ( @@ -133,7 +132,7 @@ const ProfileInfo: React.FC<PropTypes> = ({ : <Avatar className={classes.avatar} src={userInfo?.avatarUrl} /> } { - isLoading + !userInfo ? <Skeleton animation="wave" variant="rect" width={100} height={20} className={classes.skeleton} /> : ( <Typography variant="h5" className={classes.name}> @@ -144,7 +143,7 @@ const ProfileInfo: React.FC<PropTypes> = ({ } <div className={classes.profileMenu}> { - isLoading + !userInfo ? ( <> <Skeleton animation="wave" variant="rect" width={170} height={20} className={classes.skeleton} /> diff --git a/src/pages/ProfilePage/ProfilePage.tsx b/src/pages/ProfilePage/ProfilePage.tsx index ae94b9f..4769999 100644 --- a/src/pages/ProfilePage/ProfilePage.tsx +++ b/src/pages/ProfilePage/ProfilePage.tsx @@ -1,59 +1,41 @@ -import React, { useState, useEffect } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { useHistory, useParams } from 'react-router-dom'; -import { User, Poll } from 'which-types'; +import { Poll } from 'which-types'; import { Container } from '@material-ui/core'; import ProfileInfo from './ProfileInfo'; import Feed from '../../components/Feed/Feed'; -import { get } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; +import { useUser, useProfile } from '../../hooks/APIClient'; const ProfilePage: React.FC = () => { - const [userInfo, setUserInfo] = useState<User>(); - const [polls, setPolls] = useState<Poll[]>([]); - const [totalVotes, setTotalVotes] = useState<number>(0); - const [isInfoLoading, setIsInfoLoading] = useState(false); - const [isPollsLoading, setIsPollsLoading] = useState(false); const history = useHistory(); const { username } = useParams(); const { user } = useAuth(); + const { data: userInfo, mutate: setUserInfo } = useUser(username); + const { data: polls, mutate: fetchPolls } = useProfile(userInfo?._id); + useEffect(() => { - setIsInfoLoading(true); + fetchPolls(); + }, [userInfo, fetchPolls]) - const redirect = () => { + useEffect(() => { + if (!username) { if (user) history.push(`/profile/${user.username}`); else history.push('/login'); }; + }, [username, history, user]); - if (username) { - get(`/users?username=${username}`).then(response => { - if (!response.data.length) redirect(); // TODO: handle this case - setUserInfo(response.data[0]); - setIsInfoLoading(false); - }).catch(() => redirect()); - } else redirect(); - }, [username, user, history]); - - - useEffect(() => { - if (userInfo?._id) { - setIsPollsLoading(true); - get(`/profiles/${userInfo._id}`).then(response => { - setIsPollsLoading(false); - setPolls([]); - setPolls(response.data); - setTotalVotes(response.data.reduce( - (total: number, current: Poll) => { - const { left, right } = current.contents; - return total + left.votes + right.votes; - }, 0 - )); - }); - } - }, [userInfo]); + const totalVotes = useCallback( + polls.reduce( + (total: number, current: Poll) => { + const { left, right } = current.contents; + return total + left.votes + right.votes; + }, 0 + ), [polls]); return ( <Container maxWidth="sm" disableGutters> @@ -62,9 +44,8 @@ const ProfilePage: React.FC = () => { setUserInfo={setUserInfo} savedPolls={polls.length} totalVotes={totalVotes} - isLoading={isInfoLoading} /> - {isPollsLoading ? <Feed polls={[]} /> : (polls.length > 0 && <Feed polls={polls} />)} + <Feed polls={polls} /> </Container> ); }; |