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>    );  }; | 
