☁️ TIL 0218

JB·2022년 2월 18일
0

CodeCamp FE 05

목록 보기
27/33

⬇️ Main Note
https://docs.google.com/document/d/18aytI_bQKBKqEMolbcuUG-w5hMBh_Um_QRT2Ojfb2E4/edit


🌵 [Generic]

any vs. unknown

//1. anyType
export const getAny = (args: any) => {
  const answer = args + 2; //result => J2
  return answer;
};

const myResult1 = getAny("J");
console.log(myResult1);
//Same to js when used 'any'
//for any type, it doesn't matter what kind of arguments are put in. 


//2. unknown type
const getUnknown = (args: unknown) => {
  //When argument is unknown type
  if (typeof args === "number") {
    const answer = args + 2;
  } else {
    return "Enter the number";
  }

  const answer = args + 2;
  return answer;
};

const myResult2 = getUnknown("철수"); 
// Whether number+2 comes out or "Enter the number" comes out.
console.log(myResult2);
  • Both any and unknown functions same as 'javascript'.
  • unknown type is warning the developer to make sure the coding is done safely.
  • Using unknown over any is preferred.

Generic

export function getAny(arg: any): any {
  return arg;
}
const myResult31 = getAny("철수");
const myResult32 = getAny(123);
const myResult33 = getAny(true);

console.log(myResult31);
console.log(myResult32);
console.log(myResult33);

export function getGeneric<MyType>(arg: MyType): MyType {
  return arg;
}

const aaa: string = "JJ"; 
//--> saved as string and executed as string
const bbb: number = 8;
const ccc: boolean = true;

const result41 = getGeneric(aaa);
const result41 = getGeneric(bbb);
const result41 = getGeneric(ccc);

//Checking
console.log(result41);
console.log(result41);
console.log(result41);

🌵 [Browser Storage]

Session Storage: When the user exits the browser and comes back to the browser, the data gets re-set.
Local Storage: The data is still activated even the user exits and comes back to the browser.
Cookie: Same as local storage, but expiration time exists.

It's a bad idea to save heavy data inside cookies.

  • When browser requests API to backend server, the request is automatically sent with the cookies.
  • When too much cookie are saved, there are too much data sent
  • The backend can add data inside the cookie and save it. So when the response is sent, that saved data is also sent to the browser.
    --> The data that is important for security is mostly used with cookie.
export default function BrowserStoragePage() {
  const onClickSaveCookie = () => {
    document.cookie = "aaa=철수";
    document.cookie = "zzz=맹구";
  };

  const onClickSaveLocal = () => {
    localStorage.setItem("bbb", "영희");
  };

  const onClickSaveSession = () => {
    sessionStorage.setItem("ccc", "훈이");
  };

  const onClickGetCookie = () => {
    // const aaa = document.cookie;
    // console.log(aaa); //aaa=철수; zzz=맹구 => 세미콜론이 붙어서 나옴 ;

    const aaa = document.cookie //
      .split("; ") //["aaa=철수" , "zzz=맹구"]
      .filter((el) => el.startsWith("aaa="))[0]; // ["aaa=철수"][0] 필터는 배열이기에 철수가 배열에 담겨서 출력

    const result = aaa.replace("aaa=", "");

    console.log(result);
  };

  const onClickGetLocal = () => {
    const bbb = localStorage.getItem("bbb");
    console.log(bbb);
  };
  const onClickGetSession = () => {
    const ccc = sessionStorage.getItem("ccc");
    console.log(ccc);
  };

  return (
    <div>
      <button onClick={onClickSaveCookie}>쿠키 저장</button>
      <button onClick={onClickSaveLocal}>로컬 저장</button>
      <button onClick={onClickSaveSession}>세션 저장</button>
      <br />
      <button onClick={onClickGetCookie}>쿠키 조회</button>
      <button onClick={onClickGetLocal}>로컬 조회</button>
      <button onClick={onClickGetSession}>세션 조회</button>
    </div>
  );
}

localStorage.getItem("accessToken")
--> This can also be approached by the hacker.
document.cookie
--> Functions the same as localStorage, but it has secure, httpOnly, etc.
--> When httlpOnly is set ture, it is safely sent and received.


🌵 [Basket]

//게시글 장바구니에 담기
import { gql, useQuery } from "@apollo/client";
import { IBoard } from "../../src/commons/types/generated/types";

const FETCH_BOARDS = gql`
  query fetchBoards {
    fetchBoards {
      _id
      writer
      title
    }
  }
`;

export default function BasketPage() {
  const { data } = useQuery(FETCH_BOARDS);

  const onClickBasket = (el) => () => {
    console.log(el);

    // localStorage.getItem("Basket") //문자열임 "{}" 그래서 객체로 돌려놔야함
    const baskets = JSON.parse(localStorage.getItem("basket") || "[]");
    //데이터가 있으면 basket에 더해나가고 없으면 빈객체에 더해나가고

    const temp = baskets.filter((basketEl: IBoard) => basketEl._id === el._id);
    //basketEl은 장바구니에 담겨있는 element
    //같은게 있다면 필터링해줘
    //temp에 아이디가 담겨있다는건 이미 기존에 한번 담겨있었다는거
    //temp의 길이가 0인지 1인지에 따라서 구분할 수 있는거임
    if (temp.length === 1) {
      //temp.length ===1 이라는건 내가 선택한게 이미 장바구니에 있다는거 (중복된 아이디 걸러내기)
      alert("이미 장바구니에 담겨있습니다");
      return;
    }

    //Board 인자 제거하고싶음
    // delete el.__typename //원본 건드리는거 좋은 방법이 아님
    const { __typename, ...newEl } = el;
    baskets.push(newEl);
    localStorage.setItem("basket", JSON.stringify(baskets));
  };

  return (
    <div>
      {data?.fetchBoards.map((el: IBoard) => (
        <div key={el._id}>
          <span>{el.writer}</span>
          <span>{el.title}</span>
          <button onClick={onClickBasket(el)}>장바구니 담기</button>
        </div>
      ))}
    </div>
  );
}
//비회원 장바구니 조회
import { useEffect, useState } from "react";
import { IBoard } from "../../src/commons/types/generated/types";

export default function BasketLoggedInPage() {
  const [basketItems, setBasketItems] = useState([]);

  useEffect(() => {
    const baskets = JSON.parse(localStorage.getItem("basket") || "[]");
    setBasketItems(baskets);
  }, []);

  return (
    <div>
      <h1>비회원 장바구니</h1>
      {basketItems.map((el: IBoard) => (
        <div key={el._id}>
          <span>{el.writer}</span>
          <span>{el.title}</span>
        </div>
      ))}
    </div>
  );
}
profile
두비두밥밥

0개의 댓글