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

github에서 new OAuth application 생성하기


반환받은 client id를 fb에 붙여넣기

Generate a new client secret
// ✅ 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 형식은 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);
};
'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);
      })
    : [];
  // ...생략
// ✅ 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;