210814_칵테일 검색 사이트(clone-coding)

Bitnara Lee·2021년 8월 14일
0

cocktail 검색 사이트

유튜브 react 강의 중 발견해서, API 다루는 법에 익숙해질 겸 clone 해보았다.

구현 기능

cocktail API를 이용해 칵테일들을 불러온다.
search bar 존재 - 원하는 칵테일을 검색할 수 있다. (타이핑 시작하면 칵테일들이 검색되기 시작)
원하는 칵테일을 클릭 시 자세한 정보를 볼 수 있다.
Home, About, Cocktail, error 페이지 라우팅
로딩 화면 구현

알게 된 점

jsx

리액트에서 src안 폴더 나눌때: 크게 page, components로 구분한다. (경우 따라 다른 폴더 추가)

useCallback : Returns a memoized callback.

useContext / useGlobalContext

조금 익숙해진것 같기도? 매번 불필요한 부분에 props를 전달하지 않아도 state를 가져올 수 있다

redux와 useContext의 차이점

항상 헷갈렸는데 잘 설명해준 페이지를 찾았다!

useContextRedux
hook상태 관리 라이브러리
data 공유data,state 관리
Context value에 의해 변한다pure function(리듀서들)에 의해 변한다
state를 바꿀수 ostate는 read-only, 직접 바꿀 수 x
provider의 prop이 바뀔 시 모든 컴포넌트들이 다시 렌더링 된다업데이트되는 컴포넌트만 다시 렌더링
작은 어플리케이션에 적합큰 어플리케이션에 적합
이해하기 쉽고 적은 코드이해하기 복잡

redux vs useContext

fetch 이용 칵테일 data 받아오는 프로세스


import React, { useState, useContext, useEffect } from "react";
import { useCallback } from "react";

const url = "https://www.thecocktaildb.com/api/json/v1/1/search.php?s=";
const AppContext = React.createContext();

const AppProvider = ({ children }) => {
  const [loading, setLoading] = useState(false);
  const [searchTerm, setSearchTerm] = useState("a");
  const [cocktails, setCocktails] = useState([]);

  const fetchDrinks = useCallback(async () => {
    setLoading(true);
    try {
      const response = await fetch(
        `${url}${searchTerm}`
      );    /*   이렇게 url 페치 가능!(searchTerm은 input값!) 신기하당   */
      const data = await response.json();
      
      const { drinks } = data;
      if (drinks) {
        const newCocktails = drinks.map((item) => {
          const {
            idDrink,
            strDrink,
            strDrinkThumb,
            strAlcoholic,
            strGlass
          } = item;
          return {
            id: idDrink,
            name: strDrink,
            image: strDrinkThumb,
            info: strAlcoholic,
            glass: strGlass
          };
        });
        setCocktails(newCocktails);
      } else {
        setCocktails([]);
      }
      setLoading(false);
    } catch (error) {
      console.log(error);
      setLoading(false);
    }
  }, [searchTerm]);
  useEffect(() => {
    fetchDrinks();
  }, [searchTerm, fetchDrinks]);
  
    /*  받은 응답 변수로 지정해서 그 속의 프로퍼티를 빼냄, if조건문 안에서 map해서 그 안의 
      값들 또 꺼냄!(콘솔에 찍어서 프로퍼티 확인)
      id 및 등등 객체로 저장해서 리턴!(맵이므로 저절로 배열로 나옴) -> 이것을 set~으로 상태변경! 
      없으면 빈배열! either way you have to change the Loding state one you've done  */

  return (
    <AppContext.Provider
      value={{
        loading,
        cocktails,
        setSearchTerm
      }}
    >
      {children}
    </AppContext.Provider>
  );
};
// make sure use
export const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppContext, AppProvider };
  
   {cocktails.map((item) => {
       return (
         <Cocktail key={item.id} {...item} />
       ); /*   !!!!!이렇게 스프레드로 다 전달가능!!! */
    })}
--------------------------------------------------------

   <Link to={`/cocktail/${id}`} className="btn btn-primary btn-details">
       details
   </Link>
/*     !!이렇게 받은 id prop을 링크할수 있다 - 클릭하면 해당의 세부페이지로 이동!!*/

useParams()
useParams returns an object of key/value pairs of URL parameters.

import { useParams } from 'react-router-dom';

export default function Profile() {
  const { username } = useParams(); // 보통 이렇게 구조분해로 꺼내고, rest API 등 이용
  const [user, setUser] = useState(null);
  const history = useHistory();

  useEffect(() => {
    async function checkUserExists() {
      const [user] = await getUserByUsername(username);
      if (user?.userId) {
        setUser(user);
      } else {
        history.push(ROUTES.NOT_FOUND);
      }
    }
            .
            .

특정 id의 페이지를 나타낼 시 유용할 듯!
참고

css

html {
  scroll-behavior: smooth;
}

원하는 영역 선택하고 클릭하면 원하는 위치로 이동가능

스타일링 작성시 일반적 순서

:root { 글자색,애니메이션속도 등 자주 쓰일 값 변수로 저장}

*, body, global(h1~h5,p,url,img 등) 스타일링

buttons 스타일링, 

그 다음 각각 컴포넌트들에 해당하는 부분으로 나눈다(or page를 나눈다)
profile
Creative Developer

0개의 댓글