[Sleact] 슬랙 클론 코딩 - Workspace 만들기

Workspace 만들기

layouts/Workspace.tsx

import fetcher from '@utils/fetcher';
import axios from 'axios';
import React, { FC, useCallback } from 'react';
import useSWR from 'swr';

const Workspace: FC = ({ children }) => {
  const { data, error, revalidate } = useSWR('http://localhost:3095/api/users', fetcher);

  const onLogout = useCallback(() => {
    axios
      .post('http://localhost:3095/api/users/logout', null, {
        withCredentials: true,
      })
      .then(() => {
        revalidate();
      });
  }, []);
  return (
    <div>
      <button onClick={onLogout}>로그아웃</button>
      {children}
    </div>
  );
};

export default Workspace;

다른 컴포넌트에서 사용했던 요청을 똑같이 수행할 수 있다.

로그인 로직

순서가 약간 꼬였는데 로그인 로직을 다시 확인하도록 한다.
pages/LogIn/index.tsx

import useInput from '@hooks/useInput';
import { Success, Form, Error, Label, Input, LinkContainer, Button, Header } from '@pages/SignUp/styles';
import fetcher from '@utils/fetcher';
// import fetcher from '@utils/fetcher';
import axios from 'axios';
import React, { useCallback, useState } from 'react';
import { Link, Redirect } from 'react-router-dom';
import useSWR from 'swr';

const LogIn = () => {
  const { data, error, revalidate } = useSWR('http://localhost:3095/api/users', fetcher, { dedupingInterval: 100000 });
  const [logInError, setLogInError] = useState(false);
  const [email, onChangeEmail] = useInput('');
  const [password, onChangePassword] = useInput('');
  const onSubmit = useCallback(
    (e) => {
      e.preventDefault();
      setLogInError(false);
      axios
        .post('http://localhost:3095/api/users/login', { email, password }, { withCredentials: true })
        .then(() => {
          revalidate();
        })
        .catch((error) => {
          setLogInError(error.response?.data?.statusCode === 401);
        });
    },
    [email, password],
  );

  if (data) {
    return <Redirect to="/workspace/channel" />;
  }

  return (
    <div id="container">
      <Header>Sleact</Header>
      <Form onSubmit={onSubmit}>
        <Label id="email-label">
          <span>이메일 주소</span>
          <div>
            <Input type="email" id="email" name="email" value={email} onChange={onChangeEmail} />
          </div>
        </Label>
        <Label id="password-label">
          <span>비밀번호</span>
          <div>
            <Input type="password" id="password" name="password" value={password} onChange={onChangePassword} />
          </div>
          {logInError && <Error>이메일과 비밀번호 조합이 일치하지 않습니다.</Error>}
        </Label>
        <Button type="submit">로그인</Button>
      </Form>
      <LinkContainer>
        아직 회원이 아니신가요?&nbsp;
        <Link to="/signup">회원가입 하러가기</Link>
      </LinkContainer>
    </div>
  );
};

export default LogIn;

로그인 페이지는 위와 같은 코드로 작성돼있다. 처음에 data 가 false이기 때문에 바로 아래 jsx 문이 실행되고 이후 로그인을 submit하여 revalidate 하면 다시 data 를 요청하고 이번에는 data 가 들어있다. 따라서 리렌더링이 되면서 if(data)... 문에 걸려 Workspace 로 페이지가 리다이렉트되게 된다.

mutate

앞의 코드에서 revalidate 를 사용하였는데 단점이 있다. 바로 요청을 한번 더 보낸다는 것이다. 이를 보완할 수 있는 것이 바로 mutate 이다. revalidate 는 서버로 다시 요청을 보내서 데이터를 가져오는 것이고 mutate 는 서버에 요청을 보내지 않고 데이터를 수정하는 것이다.

const LogIn = () => {
  const { data, error, revalidate, mutate } = useSWR('http://localhost:3095/api/users', fetcher, {
    dedupingInterval: 100000,
  });
  const [logInError, setLogInError] = useState(false);
  const [email, onChangeEmail] = useInput('');
  const [password, onChangePassword] = useInput('');
  const onSubmit = useCallback(
    (e) => {
      e.preventDefault();
      setLogInError(false);
      axios
        .post('http://localhost:3095/api/users/login', { email, password }, { withCredentials: true })
        .then((response) => {
          mutate(response.data, false);
        })
        .catch((error) => {
          setLogInError(error.response?.data?.statusCode === 401);
        });
    },
    [email, password],
  );
  ...

mutate 를 사용하면 내가 가지고 있는 정보를 data 에 넣어준다. mutate 를 사용하면 서버에 요청을 보내기 전에 정보를 업데이트하고 이후에 그걸 서버와 맞추는데 shouldRevalidate 값을 false로 두면 그거까지 막을 수 있다.

예를 들어 인스타그램에서 하트를 눌렀을 때 바로바로 하트가 색깔이 변하면서 반응하는데 실제로 서버에 전달되기도 전에 하트가 변한다. 이는 mutate 를 활용한 것이고 사용자의 경험이 좋아진다.

(OPTIMISTIC UI) 기본적으로 성공할 것이라고 먼저 UI를 반영

좋은 웹페이지 즐겨찾기