2024.03.06 TIL - nwitter 클론코딩(fb auth github로그인), 비동기 함수 type, react query에서 type, form태그의 ts활용

Innes·2024년 3월 6일
1

TIL(Today I Learned)

목록 보기
83/147
post-thumbnail

firebase github로그인 구현하기

  1. firebase authentication에서 github 활성화 클릭!
    -> github application 정보가 필요함

  2. github에서 new OAuth application 생성하기

    https://github.com/settings/developers

  • Homepage URL에 1. fb 세번째 항목의 url의 앞 도메인부분을 붙여넣기
    (아직 배포한 홈페이지가 없으니까)
  • Authorization callback URL에는 fb 세번째 항목의 url전체를 붙여넣기
  1. 반환받은 client id를 fb에 붙여넣기

  2. Generate a new client secret

  • client secret key 생성 후 fb에 붙여넣기
    ⭐️ 생성하면 한번밖에 안보여주니까 바로 복사해서 붙여넣을 것!
  1. 코드에서 활성화하기
// ✅ github-button.tsx - nwitter 클론코딩

import {
  GithubAuthProvider,
  signInWithPopup,
  //   signInWithRedirect,
} from "firebase/auth";
import styled from "styled-components";
import { auth } from "../firebase";
import { useNavigate } from "react-router-dom";

const GithubButton = () => {
  const navigate = useNavigate();
  const onClickHandler = async () => {
    try {
      // 🧡 github로그인을 위한 provider 생성 'GithubAuthProvider()'
      const provider = new GithubAuthProvider();
      // 🧡 1. Popup으로 로그인하기
      await signInWithPopup(auth, provider);
      // 🧡 2. 다른페이지로 이동해서 깃헙로그인하기
      //   await signInWithRedirect(auth, provider);

      // 로그인 성공하면 홈으로 이동
      navigate("/");
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <Button onClick={onClickHandler}>
      <Logo src="/github-mark.svg" />
      Continue with Github
    </Button>
  );
};

export default GithubButton;

비동기 함수 type 지정하기

  • 비동기 함수의 type 형식은 Promise< T > 형식!

  • 👍🏻 올바른 type형식 코드

export const getTodo = async (): Promise<Todo[]> => {
  const res = await todoClient.get("/");
  return res.data;
};

// void인 경우도 마찬가지!
export const addTodo = async (newTodo: Todo): Promise<void> => {
  await todoClient.post("/", newTodo);
};

React-query에서 type 지정하기

  • useQuery사용하니 'Todo[] | undefined' 형식에는 반복기를 반환하는 '[Symbol.iterator]' 메서드가 있어야 합니다. 오류메시지 발생

  • 원인 : useQuery 훅에서 데이터를 가져오기 전에 todos가 undefined일 수 있기 때문에 이런 경고가 발생

  • 해결

// ✅ TodoLists.tsx - todoList typescript 리팩토링 개인과제

// useQuery로 가져오는 값의 Type 정해주기
interface TodosType {
  // data가 들어오기 전에는 undefined일 수도 있으니 함께 작성
  data: Todo[] | undefined;
  isLoading: boolean;
  isError: boolean;
}

const TodoLists: React.FC = () => {
  const [sortOrder, setSortOrder] = useState("asc");

  // ⭐️ useQuery로 불러오는 값에 type지정하기!
  const {
    data: todos,
    isLoading,
    isError,
  }: TodosType = useQuery({
    queryKey: ["todos"],
    queryFn: getTodos,
  });

  // loading, error 처리
  if (isLoading) {
    return <div>Loading...</div>;
  }
  if (isError) {
    return <div>Error</div>;
  }

  const onSortChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setSortOrder(e.target.value);
  };

  // ⭐️ todos가 아직 없는 경우도 생각해서 삼항연산자 작성!
  // 이 부분을 그냥 [...todos]로 시작했더니 위와 같은 오류메시지 발생함
  const sortedTodos = todos
    ? [...todos].sort((a, b) => {
        if (sortOrder === "asc") {
          return new Date(b.deadline) - new Date(a.deadline);
        }
        return new Date(a.deadline) - new Date(b.deadline);
      })
    : [];

  // ...생략

form태그 ts에서의 활용

// ✅ InputBox.tsx - todoList ts로 리팩토링

const InputBox: React.FC = () => {

  const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    // ⭐️ e.target.title.value 형식이었는데 ts에 맞게 수정!
    // get을 타고 들어가보면 string | file 이라고 나옴
    // type="text"해놨기 때문에 as string으로 type정해버리기
    
    const formData = new FormData(e.currentTarget);
    const title = formData.get("title") as string;
    const content = formData.get("content") as string;
    const deadline = formData.get("deadline") as string;

    const newTodo: Todo = {
      id: Date.now().toString(),
      title,
      content,
      isDone: false,
      deadline,
    };

    e.currentTarget.reset();
  };
  return (
    <St.Container>
      <St.Title onSubmit={onSubmitHandler} name="hello">
        <St.TitleInput name="title" placeholder="제목" />
        <St.TitleInput name="content" placeholder="내용" />
        <St.Time>
          <label htmlFor="start">마감일 :</label>
          <St.TimeInput
            type="date"
            id="start"
            name="deadline"
            min="2024-01-01"
            max="2026-12-31"
          />
        </St.Time>
        <div className="addBtn">
          <St.AddBtn type="submit" className="btn text-white">
            추가하기
          </St.AddBtn>
        </div>
      </St.Title>
    </St.Container>
  );
};

export default InputBox;
profile
꾸준히 성장하는 우상향 개발자

0개의 댓글