React :
Framework :
Animation :
- 23-08-17 : #1.0 ~ #2.2 / Styled-Components(1)
- 패키지 : 'styled-components'
- React 애플리케이션에서 컴포넌트 기반 스타일링을 위한 라이브러리
- JavaScript 코드 안에서 스타일을 정의하고, 컴포넌트와 함께 사용 가능
- 사용법
- import구문 : import styled from "styled-components";
- 기본형 : const 컴포넌트명 = styled.HTML태그명`CSS코드`;
- props 사용
- CSS : ${(인자명) => 인자명.prop명}
- 인자명은 아무거나 상관없으나, 주로 'props'로 사용
- 컴포넌트 : <컴포넌트명 prop명=prop값 />
- CSS : ${(인자명) => 인자명.prop명}
- 이미 만들어진 컴포넌트로부터 확장 가능
- 기본형 : const 컴포넌트명 = styled(기존컴포넌트명)`...`;
- 자동 완성 기능 'vscode-styled-components' 확장프로그램 사용
- 패키지 : 'styled-components'
- 23-08-18 : #2.3 ~ #3.1 / Styled-Components(2) & Set up TypeScript
- styled-components
- 컴포넌트의 스타일은 그대로 사용하되, HTML태그만을 바꾸고 싶을 때
- 컴포넌트에서 'as="HTML태그명"' 속성을 사용
- 컴포넌트 생성 시 속성값을 설정할 수 있음
- 기본형 : const 컴포넌트명 = styled.HTML태그명.attrs({속성값들})`...`;
- 'attrs'도 props를 사용해 커스텀마이징 가능
- 애니메이션
- import문 : import { keyframes } from "styled-components";
- 기본형 : const 변수명 = keyframes`...`;
- 애니메이션 적용은 기존 CSS 방식과 동일
- 선택자(pseudo selector)
- 하위 선택자가 일반 HTML태그 이더라도 선택 가능 (SCSS와 구문이 비슷함)
- 하위 선택자가 컴포넌트('as'를 사용하더라도) 사용 가능
- '${컴포넌트명}'으로 사용
- '&' 기호는 자기 자신을 가리킴
- theme : 기본적으로 모든 색상들을 가지고 있는 object
- 모든 색상들을 하나의 object 안에 넣어놨기 때문에 매우 유용함
- 추후 색상들을 바꿀 때 해당 object만 바꿔주면 되기 때문
- 설정법
- 'index'파일에서 'import { ThemeProvider } from "styled-components";'
- 사용할 컴포넌트를 '<ThemeProvider>'로 감싸주기
- '<ThemeProvider>'에 'theme' 속성 부여하기
- 사용법
- 'styled-components'에서 'props.theme' 객체를 이용하여 사용
- 'theme'에서 사용한 프로퍼티명을 사용해야 함
- 'theme' 교체 시 '<ThemeProvider>'의 'theme' 속성값만 교체하면 됨
- 컴포넌트의 스타일은 그대로 사용하되, HTML태그만을 바꾸고 싶을 때
- TypeScript : JavaScript를 기반으로 한 프로그래밍 언어, compile하여 평범한 JavaScript가 됨
- 설치법
- 새로운 프로젝트 생성 : 'npx create-react-app 폴더명 --template typescript'
- 기존 프로젝트에 TS 추가 : 'npm i --save typescript @types/node @types/react @types/react-dom @types/jest'
- TS가 패키지를 알지 못할 때
- 몇몇 패키지는 JS로 만들어졌기 때문
- 'npm i -D @types/패키지명'을 실행해 설치
- 'index.tsx'에서 root 코드가 error 날 시 아래의 코드로 수정 (+ as HTMLElement)
- const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
- 설치법
- styled-components
- 23-08-21 : #3.2 ~ #4.2 / TypeScript + React-Router-V6(1)
- TypeScript
- React Component
- Component가 필요로 하는 prop을 TS에게 설명해야 함
- interface : 객체 모양(object shape)을 TS에게 설명해주는 TS의 개념
- 선언 기본형 : interface 인터페이스명 { ... }
- 사용 기본형 : ':타입명'
- 'styled-components'에서 prop을 받으려면, 타입을 선언해 주어야 함
- 기본형 : const 컴포넌트명 = styled.HTML태그명<타입명>`...`;
- 선택적(optional) props
- '?'기호를 사용해 선택적 prop 설정 가능
- 병합연산자 '??' : 'null' 또는 'undefined'일 때 기본값 지정 가능
- React State
- TS가 'useState'의 초깃값을 보고, 자동적으로 타입을 추론함
- 가끔 2개 이상의 타입을 사용하는 경우, 직접 타입을 선언해 주어야 함
- 기본형 : const [변수명, 함수명] = useState<타입명>(초깃값);
- React Event
- 'addEventListener'에 인자로 사용하는 'event'에 타입을 설명해야 함
- React Component
- TypeScript
- 23-08-22 : #5.0 ~ #5.3 / React-Router + createGlobalStyle + fetchAPI
- React-Router v6
- 설정법
- '/src/routes' 폴더에 화면에 보여줄 컴포넌트 파일들을 생성하기
- '/src/Router.tsx' 라우터 파일 생성 및 설정하기
- { BrowserRouter, Routes, Route } 등
- 라우터 파일을 렌더링하기
- 'App.tsx'에서 <Router />를 return하여 렌더링
- 'useParams()' : URL 파라미터 값(object)을 받을 수 있음
- <Link> : React-Router 내에서 페이지를 이동하는 태그
- 기본형 : <Link to="이동할URL">내용</Link>
- CSS에서는 'Link' 대신 'a'태그로 사용 가능
- 설정법
- 'styled-components'에서의 전역 스타일링
- 'createGlobalStyle' 프로퍼티를 사용해 렌더링 시 전역 스코프에 스타일 사용
- 기본형 : const 컴포넌트명 = createGlobalStyle` ... `;
- '<컴포넌트명 />'을 사용해 return
- 폰트 사용 시 '@import'문이 제대로 적용되지 않으므로, 'index.html'의 <head>에 넣은 후 사용
- 'createGlobalStyle' 프로퍼티를 사용해 렌더링 시 전역 스코프에 스타일 사용
- <Fragment> : 일종의 유령 컴포넌트
- 부모 element 없이 서로 붙어있는 많은 컴포넌트들을 return할 수 있게 해줌
- <div> element 사용 없이 렌더링
- 무수한 <div>가 사용되는 것을 방지함
- 주로 빈 태그(<></>)로 사용함
- 부모 element 없이 서로 붙어있는 많은 컴포넌트들을 return할 수 있게 해줌
- fetch API
- API를 통해 데이터를 가져올 때 TS에게 데이터의 타입을 알려주어야 함 (interface)
- 'axios'패키지 사용 시 json 형식으로 바로 가져옴
- 기본형 : const 변수명 = await axios("URL주소");
- 즉시 실행 함수 표현 (IIFE; Immediately Invoked Function Expression)
- 정의되자마자 즉시 실행되는 함수 (선언 후 실행할 필요 없음)
- 기본형 : (함수선언)();
- React-Router v6
- 23-08-23 : #5.4 ~ #5.8 / Link state + Nested Routes + useMatch
- <Link> state : 화면에 보이지 않는 방식으로 다른 페이지에 데이터를 보내는 방법
- 'state' 속성을 사용해 object 형식으로 데이터 전송 가능
- 'useLocation()'을 사용해 데이터를 수신
- 받은 데이터의 타입을 TS에게 설명해주어야 함
- react-router-dom v6부터 'useLocation()'의 제네릭을 지원하지 않음
- 'as 인터페이스명' 방식으로 사용
- '?.' 옵셔널체이닝
- 객체의 프로퍼티에 접근 시 해당 프로퍼티가 존재하지 않는 경우, Error를 발생시키지 않고 'undefined'를 반환함
- Nested Routes : route 안에 존재하는 또 다른 route
- 웹사이트에서 탭을 사용할 때 유용함 (스크린 안에 섹션이 많을 때 등)
- 생성법 (자식 route를 라우터 파일에 작성하는 방법)
- 라우터 파일에서 부모 <Route>에 감싸서 사용하기
- 상대경로 URL을 지원하므로, 자식 route의 path는 상대경로를 사용
- 자식 route가 어디에 render가 될지 부모 route 컴포넌트에서 '<Outlet />'으로 표시하기
- 라우터 파일에서 부모 <Route>에 감싸서 사용하기
- useMatch() : 현재 URL 위치를 기준으로 지정된 경로에 대한 일치 데이터를 반환
- 기본형 : const 변수명 = useMatch("URL주소");
- import { useMatch } from "react-router-dom";
- 상대경로 URL 사용 불가능
- 사용자가 선택한 URL에 위치하면 object를 반환, 그렇지않으면 null을 반환
- 기본형 : const 변수명 = useMatch("URL주소");
- <Link> state : 화면에 보이지 않는 방식으로 다른 페이지에 데이터를 보내는 방법
- 23-08-26 : #5.9 ~ #5.11 / React-Query
- React-Query
- 편리한 방식으로 데이터를 fetch 할 수 있는 패키지
- 기존 방식인 useEffect와 useState를 활용한 fetch API를 하지 않아도 됨
- 설치법 : 'npm i @tanstack/react-query'
- 설정법
- 'index.tsx'에서 'queryClient' 객체 생성하기
- '<QueryClientProvider>' 생성 후 감싸주기
- 사용법
- fetcher 함수 생성하기
- 무조건 fetch promise(json)를 return 해주어야 함
- 'useQuery' Hook을 사용해 API 데이터 가져오기
- 기본형 : const { isLoading, data } = useQuery<제네릭>([쿼리키명], fetcher함수, ?옵션);
- queryKey : (string[]) query의 고유식별자
- fetcher함수 : 매개변수 필요 시 익명화살표함수로 작성
- 옵션 : (object)
- refetchInterval : (number) 자동으로 refetch하는 시간 주기를 설정
- isLoading : 로딩에 대한 boolean값을 return
- data : fetch가 끝난 후 데이터를 넣어줌
- 기본형 : const { isLoading, data } = useQuery<제네릭>([쿼리키명], fetcher함수, ?옵션);
- fetcher 함수 생성하기
- [핵심] 다른 페이지에 갔다가 다시 돌아와도 API를 재요청하지 않음
- React-Query가 데이터를 캐시에 저장해두기 때문
- 편리한 방식으로 데이터를 fetch 할 수 있는 패키지
- React-Query-Devtools
- 캐시에 존재하는 Query를 볼 수 있음
- React-Query의 모든 내부 동작을 시각화하는 데 도움
- 문제 발생시 디버깅 시간을 절약할 수 있음
- 기본적으로 React-Query-Devtools는 process.env.NODE_ENV === 'development'인 경우에만 번들에 포함되므로, production build 중에 제외하는 것에 대해 걱정할 필요 없음
- 설치법 : 'npm i @tanstack/react-query-devtools'
- 설정 및 사용법 : 'App.tsx'에서 'ReactQueryDevtools'를 import한 후 컴포넌트를 사용
- 'initialIsOpen={true}' 속성 필수
- 캐시에 존재하는 Query를 볼 수 있음
- React-Query
- 23-08-28 : #5.12 ~ #5.16 / ApexCharts + React-Helmet
- useOutletContext()
- 중첩된 라우트(Nested Routes)에서 부모에서 자식 컴포넌트에게 상태(state)를 공유하기 위한 목적으로 사용하는 Hook
- <Outlet /> 사용 시 하위 Route에게 변수를 넘겨줄 수 있는 기능
- 송신 기본형 : <Outlet context={{ ... }}> (object 형식으로 사용)
- 수신 기본형
- import { useOutletContext } from "react-router-dom";
- const 변수명 = useOutletContext<제네릭>();
- ApexCharts.js
- API로 받아온 데이터 등을 시각화 할 수 있는 패키지
- 설치법 : 'npm i react-apexcharts apexcharts'
- 사용법
- import ApexChart from "react-apexcharts";
- <ApexChart 속성들 />
- type : 그래프 타입 (string)
- series : 보여줄 데이터 (object[]) { name: string, data: [] }
- options : 공식문서를 참고하여 사용 (object)
- React-Helmet
- 문서의 <head>로 렌더링하는 컴포넌트형 패키지
- 설치법 : 'npm i react-helmet'
- 사용법
- import { Helmet } from "react-helmet";
- <Helmet> ... </Helmet>
- 'Using UNSAFE_componentWillMount in strict mode is not recommended
and may indicate bugs in your code.'의 Error 시 'react-helmet-async' 패키지를 사용
- 'App.tsx'에서 <Router />를 <HelmetProvider>로 감싸준 후 사용
- 'react-helmet' 패키지도 다운 받아야 함
- useOutletContext()
- 23-08-29 : [Code Challenge] use ApexChart
- 23-08-30 : #6.0 ~ #6.4 / Recoil Atom
- Recoil
- React에서 사용할 수 있는 상태 관리(state management) 라이브러리
- 설치법 : 'npm i recoil'
- 설정법 : 'index.tsx'에서 <RecoilRoot>로 앱을 감싸주기
- atom : 특정 컴포넌트에 종속되지 않으며, global state를 저장하는 기본 단위
- Recoil에서는 state값을 'atom'이라는 버블에 담아서 사용
- atom이 변경되면 컴포넌트도 변경된 값으로 re-rendering 됨
- 사용법
- 'atom'을 관리하는 파일 생성하기
- '/src/atoms.ts'
- 'atom' 생성하기
- import { atom } from "recoil";
- 기본형 : export const 변수명 = atom({ key: 키값, default: 초기값});
- [Read] 다른 컴포넌트에서 'atom' 연결하기
- 기본형 : const 변수명 = useRecoilValue(아톰명);
- [Write] 다른 컴포넌트에서 'atom' 수정하기
- 기본형 : const Setter함수 = useRecoilState(아톰명);
- 'useState()'처럼 사용하면 됨
- 'atom'을 관리하는 파일 생성하기
- Recoil
- 23-08-31 : #6.5 ~ #6.7 / React-Hook-Form(1)
- React Hook Form
- React에서 <form>을 간단하게 제작할 수 있게 도와주며, 검증까지 할 수 있는 패키지
- 기존 React에서 <form> 제작 시 setState(), value, onChange, onSubmit 등을 사용해야 했음
- 설치법 : 'npm i react-hook-form'
- 기본형
- import { useForm} from "react-hook-form";
- const { register, watch, handleSubmit, formState 등 } = useForm<제네릭>();
- register : <input>의 value와 onChange를 대체하는 속성
- name, onBlur, onChange, ref 등을 가지는 object를 return하는 함수
- 사용법 : <input {...register(이름, {검증 속성})} />
- ES6 문법을 사용해 register 함수가 반환하는 객체를 가져다가 props로 사용
- HTML 뿐만아니라 JS에서도 검증을 할 수 있도록 함
- 유효하지 않을 시 자동으로 해당 element로 focus 해줌
- ex. <input {...register("email", { required: true, minLength: 10 })} placeholder="Email" />
- handleSubmit : <form>의 'onSubmit'을 대체하고, validation을 담당함
- 기존 onSubmit의 'event.preventDefault()와 setModifier함수'를 대체
- 사용법 : <form onSubmit={handleSubmit(데이터 유효 시 호출함수, ?데이터 무효 시 호출 함수)}>
- watch : <form>의 입력값들의 변화를 관찰할 수 있게 해주는 함수
- register함수를 사용하는 모든 element들의 값을 object로 반환
- ex. console.log(watch());
- formState : 데이터 검증이 유효하지 않을 시 'formState.errors'를 참조해 error 내용 확인 가능
- 어떤 종류의 error가 발생했는지 알 수 있음
- error 발생 시 message를 보낼 수 있음
- ex. <input {...register("pw", { required: "PW is Required", minLength: { value: 5, message: "Your PW is too short" }})} />
- React에서 <form>을 간단하게 제작할 수 있게 도와주며, 검증까지 할 수 있는 패키지
- React Hook Form
- 23-09-02 : #6.8 ~ #6.10 / React-Hook-Form(2)
- React-Hook-Form
- React-Hook-Form에서는 register 사용 시 문자열을 return 하면, error 메시지를 return한다는 뜻
- setValue : 필드 값을 업데이트하는 함수
- 기본형 : const { setValue } = useForm();
- 사용법 : setValue(이름, 필드값);
- reset : <form>의 모든 필드값을 초기화하는 함수
- 기본형 : const { reset } = useForm();
- 사용법 : reset();
- React-Hook-Form - 검증
- 검증 시 정규식(Regular Expression)을 사용할 수 있음 : 'pattern' 프로퍼티 사용
- 검증 조건마다 message를 적어놨다면, error 문구를 화면에 출력 가능
- 사용자가 제출한 이후에는 message가 실시간으로 변함
- 'useForm()'에 제네릭을 명시하지 않았을시 string으로 타입을 명시해주어야 함 (as string)
- React-Hook-Form - 커스텀 검증
- 'handleSubmit()'의 인자로 사용하는 콜백함수에 커스텀 검증이 가능함
- 검증 콜백함수의 매개변수는 자동으로 <form>의 element들을 받음
- 해당 매개변수의 프로퍼티를 사용
- useForm()의 'setError' 프로퍼티는 특정한 error를 발생시켜 줌
- 기본형 : setError(레지스터명, { message: 에러메시지 });
- interface에 옵션 항목을 넣어서, 추가적인 error를 표기할 수 있음
- <form>에서 자동으로 error 항목으로 focus되게 할 수 있음
- setError()의 3번째 매개변수로 '{ shouldFocus: true }'를 부여하여 작동
- register의 검증 속성들 중 'validate' 옵션을 사용해 커스텀 규칙을 검사할 수 있음
- validate : 현재 value값을 인자로 받는 콜백함수를 값으로 가지며, boolean값을 반환함 (검증을 통과/불통과)
- 삼항조건연산자(또는 ||)를 사용해 error 메시지를 return 하도록 함
- 여러 함수(검증)가 있는 object 형태가 될 수 있음
- async 비동기로 만들어서 서버에다가 확인하고 응답을 받을 수 있음
- React-Hook-Form
- 23-09-04 : #6.11 ~ #6.15 / To-Do List
- Recoil - useRecoilState()
- atom을 'useState()'처럼 사용하는 메서드
- 'useRecoilValue()'와 'useSetRecoilState()'를 따로 사용할 필요가 없음
- 기본형 : const [값, 세터함수] = useRecoilState(아톰명);
- atom을 'useState()'처럼 사용하는 메서드
- 매개변수를 가지는 Event Listener 사용법
- element에서 event를 익명함수를 사용해 매개변수를 전달하는 방법
- ex. const onClick = (newCategory: IToDo["category"]) => { console.log("I wanna to", newCategory); }; <button onClick={() => onClick("DOING")}>Doing</button>
- element의 name 속성을 활용하는 방법
- 'name' 속성에 직접 타입을 줄 수 없기 때문에, 1번 방법을 선호
- ex. const onClick = (event: React.MouseEvent<HTMLButtonElement>) => { console.log("I wanna to", event.currentTarget.name); }; <button name="DOING" onClick={onClick}>Doing</button>
- element에서 event를 익명함수를 사용해 매개변수를 전달하는 방법
- To-Do List에서 하나의 to-do를 수정하는 방법
- 배열을 mutate하지 않으면서, 'useSetRecoilState()'로 원하는 하나의 값을 수정해야 함
- 'id' 등의 속성을 사용하여, 배열 속 원하는 element의 index 찾기
- 값 자체를 찾을 필요는 없고, 배열 index값만 알면 됨
- 배열의 '.findIndex(콜백함수)' 메서드를 사용해 조건에 맞는 index를 알아냄
- element를 업데이트하기
- 찾은 index에 대한 element를 새로운 값으로 대체(replace)해야 함
- element를 교체하는 이유는 해당 element의 위치가 바뀌지 않길 바라기 때문
- 교체할 element의 앞 부분을 새로운 배열로 생성하기
- '.slice(시작인덱스, 끝인덱스)' 메서드를 사용해 새로운 배열 생성
- 교체할 element의 뒷 부분을 새로운 배열로 생성하기
- '.slice()' 메서드의 끝인덱스를 지정하지 않을 시 끝까지 잘라서 반환함
- 교체 후 새로운 배열로 생성하기
- 배열의 스프레드 연산자(...)를 이용하여, 앞부분과 뒷부분 사이에 새 원소를 넣음
- Recoil - useRecoilState()
- 23-09-05 : #6.16 ~ #7.1 / Recoil Selector + Recoil-Persist
- Recoil - Selector
- atom의 output을 변형시키는 도구 (atom의 state 자체를 바꾸는 것이 아니라, 그의 output을 바꾸는 것)
- 선언법
const 셀렉터명 = selector({
key: 키값,
get: ({ get }) => {
const 변수명 = get(아톰명); // atom을 가져오는 문 (필수x)
......
return 값;
},
});
- get
- 인자로 받는 옵션 중의 'get'함수를 이용해 atom을 받아올 수 있으며, 여러 번 사용해 여러 개의 atom을 가져올 수 있음
- return하는 값은 해당 selector의 value가 됨
- get
- 사용법 : const 변수명 = useRecoilValue(셀렉터명);
- atom이 변하면, selector도 변함
- Recoil - Selector의 'set' 속성
- selector의 'set' 속성을 사용하여, selector에서 atom의 state를 수정할 수 있음
- 기본형
set: ({ set }, 새로운값) => {
......
set(아톰명, 수정할값); // 새로운 값과 수정할 값은 같을 필요 x
}
- 여러 개의 atom에 대해 'set()'함수를 사용할 수 있음
- 'useRecoilState()'로 selector를 불러와서 사용할 수 있음
- 첫 번째 요소 : get 프로퍼티로부터 return한 값
- 두 번째 요소 : set 프로퍼티로를 실행시키는 함수
- 'useRecoilState()'를 atom과 selector 둘다에서 사용 가능
- enum
- 열거형(enumeration)으로 정의하는 데 사용하는 데이터 형식
- 기본형: enum 변수명 { 값1, 값2, 값3, ... }
- 변수명은 대문자로 시작
- 컴퓨터는 열거 상수로 사용함
- 열거 상수는 0부터 시작하여 순서대로 1씩 증가한 값을 가지며, 순서를 따로 지정하지 않는 한 자동으로 할당됨 (수동 할당 가능, 숫자나 문자열 가능)
- 직접 같은 값으로 주어서 사용할 수 있음 (ex. enum Categories { "TO_DO" = "TO_DO" })
- 사용 시 프로퍼티 방식으로 사용 (ex. Categories.TO_DO)
- Recoil-Persist 패키지
- Recoil 상태 관리 라이브러리와 Local Storage를 통합하여, Recoil 상태를 영구적으로 저장하고 복원하는 데 도움을 주는 패키지
- 브라우저의 Local Storage를 활용하여, Recoil 상태를 지속적으로 유지할 수 있음
- 설치법 : 'npm i recoil-persist'
- 설정법
- atom 파일에서 'recoilPersist' 객체 생성하기
- const { persistAtom } = recoilPersist();
- 'recoilPersist()'의 옵션
- key : Local Storage에 데이터 저장 시 사용되는 key명
- 기본값 : "recoil-persist"
- storage : 데이터를 저장할 저장소 설정
- 기본값 : localStorage
- converter : 저장소에서 값을 직렬화/역직렬화하는 방법을 구성
- 기본값 : JSON
- key : Local Storage에 데이터 저장 시 사용되는 key명
- 'recoilPersist()'의 옵션
- const { persistAtom } = recoilPersist();
- Local Storage를 사용하고자 하는 atom에 'effect_UNSTABLE' 속성 할당하기
- 'effect_UNSTABLE: [persistAtom]' 속성만 추가하면 됨
- atom 파일에서 'recoilPersist' 객체 생성하기
- 설정만 해놓으면 Local Storage에 저장(set)과 불러오기(get)를 자동으로 실행함
- Recoil 상태 관리 라이브러리와 Local Storage를 통합하여, Recoil 상태를 영구적으로 저장하고 복원하는 데 도움을 주는 패키지
- Recoil - Selector
- 23-09-06 : #7.2 ~ #7.4 / React-Beautiful-Dnd(1)
- react-beautiful-dnd 패키지 (@hello-pangea/dnd)
- 화면에서 drag&drop을 할 수 있게 해주는 패키지
- 설치법 : 'npm i @hello-pangea/dnd'
- 'react-beautiful-dnd'는 종속성 문제때문에 React 18버전에서 제대로 동작하지 않고, 해당 패키지가 더 이상 없뎃이므로 비추천
- 웹 페이지에서 작동이 되지 않을 시 'React.StrictMode'를 제거할 것
- <DragDropContext />
- drag&drop을 가능하게 하고 싶은 앱의 한 부분(영역)
- 앱 전체가 아닌 사용자가 drag&drop을 할 특정 영역에만 생성하도록 함
- 기본형 : <DragDropContext onDragEnd={콜백함수}> ... </DragDropContext>
- onDragEnd : [필수] 사용자가 drag를 끝낸 시점에 실행하는 콜백함수
- 콜백함수에 내용이 없다면, drag&drop이 끝날 시 원래대로 돌아옴
- [필수] 태그 사이에는 children(하위 태그)이 있어야 함
- onDragEnd : [필수] 사용자가 drag를 끝낸 시점에 실행하는 콜백함수
- drag&drop을 가능하게 하고 싶은 앱의 한 부분(영역)
- <Droppable />
- 어떤 것을 드롭할 수 있는 영역(list)
- 기본형 : <Droppable droppableId="이름"> ... </Droppable>
- droppableId : [필수] drop할 수 있는 영역이 여러 개일 수 있기 때문
- [필수] 태그 사이에는 children(콜백함수 JSX)이 있어야 함
- 콜백함수의 첫 번째 인자로 'provided'를 받음 (위치만 중요하지, 이름은 아무거나 가능)
- 콜백함수에서 사용되는 JSX에 'provided.droppableProps'의 모든 프로퍼티와 'ref'속성으로 'provided.innerRef'를 주어야 함
- ex. {(provided) => <ul ref={provided.innerRef} {...provided.droppableProps}> ... </ul>}
- 'provided.placeholder' : </Droppable>이 끝날 때 두어, drag&drop 시 <Droppable>의 사이즈가 이상하게 변하는 것을 막음
- <Droppable>의 하위 콜백함수에서 사용된 JSX의 닫힌 태그 바로 앞에서 사용
- <Draggable />
- 사용자가 drag할 수 있는 영역(list에 있는 item)
- 기본형 : <Draggable draggableId="이름" index={인덱스}> ...... </Draggable>
- draggableId : [필수] drop할 수 있는 영역이 여러 개일 수 있기 때문
- 'key'속성 사용 시 'draggableId'의 속성값과 같아야 함 (drag&drop 할 수 있기 때문)
- index : [필수] sorting을 위한 프로퍼티
- [필수] 태그 사이에는 children(콜백함수 JSX)이 있어야 함
- 콜백함수의 첫 번째 인자로 'provided'를 받음 (위치만 중요하지, 이름은 아무거나 가능)
- provided.draggableProps : 해당 element의 drag 기능
- provided.dragHandleProps : drag하기 위해 잡을 수 있는 영역
- 해당 프로퍼티를 준 element를 drag 해야함
- 콜백함수에서 사용되는 JSX에 'provided.draggableProps'의 모든 프로퍼티와 'provided.dragHandleProps'의 모든 프로퍼티와 'ref'속성으로 'provided.innerRef'를 주어야 함
- ex. {(provided) => <li ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}> ...... </li>}
- draggableId : [필수] drop할 수 있는 영역이 여러 개일 수 있기 때문
- react-beautiful-dnd 패키지 (@hello-pangea/dnd)
- 23-09-07 : #7.5 ~ #7.11 / React-Beautiful-Dnd(2)
- <DragDropContext> - 'onDragEnd'
- 'onDragEnd' 프로퍼티는 drag&drop이 끝날 때 실행하는 함수
- 어떤 일이 일어났는지에 대한 정보를 담고있는 argument를 제공함
- 'onDragEnd'의 인자의 타입은 'DropResult' (타입 문서 참조)
- draggableId : drag&drop을 한 element를 알려줌
- destination : 목적지의 정보 { droppableId, index }
- source : 출발지의 정보 { droppableId, index }
- drag&drop을 한 element를 저장한 배열에서도 똑같이 만들어주어야 함
- 배열에서 drag한 element를 삭제하기
- 'source.index'를 참조해 삭제
- 배열.splice(시작인덱스, 삭제할갯수) : 해당 item을 배열에서 삭제하는 메서드
- 원본 배열이 바뀌는 mutation이 일어나므로, 먼저 원본을 복사한 후 사용해야 함
- 배열 복사 시 스프레드 연산자(...)를 사용한 '[...배열명]' 방식으로 복사해야 함
- 배열은 그냥 복사 시 주소값만 연결되기 때문
- 삭제한 element를 배열에서 drop한 위치에 생성하기
- 'destination.index'와 'draggableId'를 참조해 생성
- 배열.splice(시작인덱스, 삭제할갯수, 아이템) : 삭제할 갯수를 0으로 하고 아이템 매개변수를 넣어주면, 배열의 해당 인덱스에 아이템을 추가할 수 있음
- 'destination'이 없을 수도 있음 (같은 자리에 drag&drop을 할 수도 있기 때문)
- 배열에서 drag한 element를 삭제하기
- 문제 발생 : drag&drop 시 가끔 content가 떨리는 현상 (최적화 문제)
- 이유 : 부모 component의 state가 변하면, 자식 component들까지 전부 re-rendering되기 때문 (React의 기본 동작 방식)
- drag하는 component 이외에도, 형제 component 등 전부가 re-rendering 됨
- console.log()로 확인 가능
- 해결 : 'React.memo()'를 사용해 해결
- 해당 component의 prop이 변하지 않았다면, re-rendering하지 않도록 함
- 'export default React.memo(컴포넌트명);'을 사용
- 이유 : 부모 component의 state가 변하면, 자식 component들까지 전부 re-rendering되기 때문 (React의 기본 동작 방식)
- 다수의 보드(<Droppable>) 사용하기
- 준비 과정
- 다수의 보드를 사용하기 위해, atomState를 여러 개의 Array를 가지는 Object로 사용하기
- '.map()'을 사용해 여러 개의 보드를 rendering하기
- 'Object.keys(객체명)'으로 해당 객체의 key명들을 배열로 뽑아낼 수 있음
- 'Object.keys(객체명).map(키명 => 객체명[키명])'을 사용해 각 key의 값들을 뽑아낼 수 있음
- 사용자가 여러 개의 보드를 생성/삭제 할 수 있으니, interface를 설정해줘야 함
- ex. interface IToDoState { [key: string]: string[]; }
- 'Object.keys(객체명)'으로 해당 객체의 key명들을 배열로 뽑아낼 수 있음
- drag&drop을 사용하려면, 현재 위치의 Array에서 제거한 후 새로운 위치의 Array에 붙여놓기
- 'source'와 'destination'을 참조 가능
- source의 보드와 destination의 보드가 같은지 체크하기
- 각각 '.droppableId'를 통해 참조 가능
- 같은 보드에서 이동이 일어날 시
- 수정이 일어난 보드만 복사하기
- 복사한 보드를 수정한 후, 다른 보드들 옆에 놓기
- 다른 보드로 이동이 일어날 시
- 출발지 보드와 도착지 보드를 복사하기
- 복사한 보드들을 수정한 후, 다른 보드들 옆에 놓기
- 다른 보드들 옆에 놓기 위해 스프레드연산자(...)와 computed property name을 이용해야 하며(ES6), 전체 객체가 먼저 사용되어야 함
- ex. return { ...allBoards, [source.droppableId]: boardCopy }
- 준비 과정
- 문제 발생 : item을 가지고 있지 않는 보드에는 해당 보드 맨 위로 이동해야지만 item을 받을 수 있는 불편함
- CSS로 받는 부분(<Droppable>의 하위 element)의 영역을 부모 element에 가득 차게끔 만들기
- 해결 방법
- 부모 element에 'display: flex;' CSS를 부여하기
- 자식 element에 'flex-grow: 1;' CSS를 부여하기
- 자식 element의 영역이 부모 element에 가득 차게끔 만듦
- <Droppable>, <Draggable> - snapshot
- <Droppable> 또는 <Draggable>의 children으로 사용되는 콜백함수의 두 번째 인자로 'snapshot'을 사용할 수 있음
- 두 번째 자리가 중요함, 이름은 아무거나 상관없음
- 'snapshot'의 프로퍼티는 형식 정의 파일에서 확인 가능
- isDraggingOver : 보드로 들어올 때의 dragging에 대한 boolean값을 받음
- 사용자가 보드 위로 drag해서 들어오고 있는지 알려줌
- draggingFormThisWith : 사용자가 해당 보드로부터 drag를 시작했는지도 알려줌
- 사용자가 어떤 보드를 떠난다면, 그 보드로부터 drag를 시작했다는 뜻
- DraggableId | undefined
- 'Boolean(draggingFormThisWith)'로 사용 시 drag하여 해당 보드를 떠나면 true
- isDraggingOver : 보드로 들어올 때의 dragging에 대한 boolean값을 받음
- 사용법 : <Droppable>의 콜백함수 JSX element에서 프로퍼티를 부여하여 사용
- element는 snapshot의 프로퍼티를 모르기 때문에, 형식 정의를 해주어야 함
- 프로퍼티를 이용해 styled-components로 CSS 적용 가능
- <Droppable> 또는 <Draggable>의 children으로 사용되는 콜백함수의 두 번째 인자로 'snapshot'을 사용할 수 있음
- <DragDropContext> - 'onDragEnd'
- 23-09-08 : #7.12 ~ #7.16 / React-Beautiful-Dnd(3) + Code Challenge(1)
- React - ref 속성
- React.js component를 통해 HTML element를 가져와서 그걸 변형시킬 수 있도록 해줌
- aka. vanilla JS의 document.getElementById()
- 기본형
const 변수명 = useRef<제네릭>(null);
<태그명 ref={변수명} />
- 보통 'useRef()'의 인자로 null값을 사용함 (참조할 element를 초기화한 후 사용하기 위함)
- React.js component를 통해 HTML element를 가져와서 그걸 변형시킬 수 있도록 해줌
- To-Do의 타입 교체
- 'string[]'에서 '{ id:number, text: string }[]'인 타입으로 교체
- 문제 발생 : 'onDragEnd'에서 'draggableId'를 참조해 재배열 한 것을 바꾸어줘야 함
- 기존의 string[] 타입에서는 draggableId = item 이어서 쉬웠음
- 지금의 draggableId는 string타입의 id 프로퍼티 값임
- 해결 방법 : '.index' 프로퍼티를 이용해서 item을 찾기
- 'source.index'를 통해 타겟(Object)을 찾은 후 사용
- React - ref 속성
- 23-09-09 ~ 10 : Code Challenge(2)
- 23-09-12 : #8.0 ~ #8.6 / Animations(1)
- Framer-Motion 패키지
- 애니메이션을 만들 수 있는 React.js용 라이브러리
- CSS transition 코드 없이 작동하는 애니메이션
- 설치법 : 'npm i framer-motion'
- 설정법 : 'import { motion } from "framer-motion";'
- 규칙 : 'motion'의 프로퍼티를 HTML태그명으로 사용해야지 애니메이션을 만들 수 있음
- 기본형 : <motion.HTML태그명>
- 'styled-components'에서 motion 애니메이션 태그 생성법
- 기본형 : const 컴포넌트명 = styled(태그명)` ... `;
- 애니메이션을 만들 수 있는 React.js용 라이브러리
- motion의 props
- 기본적으로 'style'프로퍼티처럼 연속하는 2개의 중괄호를 사용 ({{, }})
- initial : element의 초기 상태를 나타냄
- animate : element의 최종 상태를 나타냄
- transition : 트랜지션 프로퍼티
- delay : n초 후에 애니메이션 발생 [seconds]
- duration : n초 동안 애니메이션 발생 [seconds]
- 애니메이션 만들기
- 기본값으로 살짝 튕기는 듯한 느낌으로 'type: "spring"'이 적용되어 있음
- stiffness : [number] 경직됨
- damping : [number] 반동력
- bounce : 튕기는 정도
- mass : 물체의 질량
- 'type: "tween"' : 선형적(linear)
- 기본값으로 살짝 튕기는 듯한 느낌으로 'type: "spring"'이 적용되어 있음
- Variants
- 애니메이션 설정을 분리된 Object로 옮겨서 사용하는 방법
- 초기 상태와 최종 상태를 명시해야 함
- 이름은 아무거나 사용 가능하지만, 사용 시 이름이 같아야 함
- 최종 상태의 옵션으로 'transition'을 넣어줄 수 있음
- Variants에 프로퍼티를 더 추가할 수 있으며, :hover 등에 사용할 수 있음
- 기본형 const 변수명 = { 초기상태명 : { ... }, 최종상태명 : {}, } <태그명 variants={변수명} initial="초기상태명" animate="최종상태명">
- Variants - 자식 컴포넌트
- 부모 컴포넌트가 variants, initial, animate를 갖고 있을 때 기본값으로 자식 컴포넌트에도 적용됨
- 자동으로 부모의 initial, animate의 값을 상속받음
- 자식 컴포넌트에 새로운 variants 적용 시 variants만 적어주면 됨
- 단, 상태명은 부모 variants와 같은 이름을 사용해야 함
- 자동으로 initial, animate를 복붙하기 때문
- 단, 상태명은 부모 variants와 같은 이름을 사용해야 함
- 부모 컴포넌트에서 자식 컴포넌트의 'delay'를 조절 가능
- delayChildren : 자식 컴포넌트들의 delay 시간 [seconds]
- staggerChildren : 각각의 자식 컴포넌트들의 delay 시차 [seconds]
- 부모 컴포넌트가 variants, initial, animate를 갖고 있을 때 기본값으로 자식 컴포넌트에도 적용됨
- event에 따른 animation
- 'while이벤트명' 속성을 사용
- { whileHover, whileTap, whileDrag, whileFocus, whileInView }
- variants에서 상태명 키-값을 사용 가능
- 'while이벤트명' 속성을 사용
- Dragging (드래깅)
- 사용법 : 컴포넌트에 'drag'속성을 부여하면 됨
- 'drag="x"' : x축으로만 drag 가능
- 'drag="y"' : y축으로만 drag 가능
- whileDrag : drag하는 동안 나타나는 animation 속성
- 색을 사용할 때 number값(rgb, hex 등)을 사용해야지 자동으로 transition이 작동함
- 그렇지 않으면(string 등), 즉각적으로 색이 변함
- 색을 사용할 때 number값(rgb, hex 등)을 사용해야지 자동으로 transition이 작동함
- dragConstraints : drag가 허용될 수 있는 영역
- { top, bottom, left, right }
- 제한된 영역을 넘어서면, 영역 내로 되돌아감
- dragSnapToOrigin : drag가 끝나면 처음 위치로 되돌아가는 속성
- dragElastic : drag 시의 당기는 힘
- 0~1 사이의 값을 가짐 (기본값 0.5)
- 0 : drag요소가 제한된 영역 밖으로 나갈 수 없음
- 1 : drag요소와 마우스 커서가 같은 위치로 drag함
- 제한된 영역 내에서만 dragging을 허용시키는 방법
- 제한된 영역을 가지는 div 컴포넌트 내에 drag할 수 있는 컴포넌트 생성하기
- 제한된 영역(부모) 컴포넌트에 CSS 'overflow: hidden' 속성 부여하기
- 'overflow: hidden' : 하위 요소가 부모 요소의 내에서만 보이도록 함 (초과된 부분은 보이지 않음)
- 제한된영역 내에서만 drag할 수 있도록 제약을 넣기
- 수학적 방법
- ex. 제한영역=600x600 / 드래그요소=200x200 dragConstraints={{ top: -200, bottom: 200, left: -200, right: 200 }}
- 'ref' 속성을 이용하는 방법
- 제한된 영역의 'ref'를 설정한 후, 드래깅 요소의 'dragConstraints'에 제한된 영역의 ref를 할당
- 기본형 : const 변수명 = useRef<제네릭>(null);
- 수학적 방법
- 사용법 : 컴포넌트에 'drag'속성을 부여하면 됨
- Framer-Motion 패키지
- 23-09-14 : #8.7 ~ #8.13 / Animations(2)
- Motion Value
- 애니메이션 내의 수치를 tracking할 때 필요한 변수
- dragging을 왼쪽/오른쪽에 따라 배경색을 바꾸는 등
- Motion Value가 바뀌어도, 컴포넌트가 re-rendering하지 않음 (state값이 아니기 때문)
- 사용법
const 변수명 = useMotionValue(초기값);
<태그명 style={{ 속성: 변수명 }} />
- 변수명.get() : 현재 값을 불러오는 메서드
- 변수명.set() : 해당 값으로 처리하는 메서드
- ex. const x = useMotionValue(); <button onClick={() => x.set(200)}>Click me</button> <Box style={{ x }} drag="x" />
- 애니메이션 내의 수치를 tracking할 때 필요한 변수
- useMotionValueEvent()
- 'motion value'값을 알아보기 위해 사용하는 메서드
- 기본형 : useMotionValueEvent(변수명, 이벤트명, 콜백함수);
- 이벤트명 중 "change"는 콜백함수의 인자로 'latest'값(= .get()) 제공
- useTransform()
- 'motion value' 입력 범위를 출력 범위로 매핑하는 데 사용하는 메서드
- 애니메이션과 상호작용을 동적으로 제어하고 관리하기 위해 사용ㅇ
- 기본형 : const 변수명 = useTransform(모션값변수명, 입력배열, 출력배열);
- 모션값변수명 : 'useMotionValue' 값
- 입력 배열 : 입력 값 범위
- 출력 배열 : 출력 값 범위
- 입력 범위 내에 있을 때, 해당 값에 대한 출력 범위 값을 반환함
- 입력 범위를 벗어나도 최소/최대 출력 범위를 반환함
- 범위 내에서는 점진적으로 값을 반환함
- 'motion value' 입력 범위를 출력 범위로 매핑하는 데 사용하는 메서드
- useScroll()
- 현재 페이지 스크롤의 'motion value'값을 반환하는 메서드
- 기본형 : const { 프로퍼티명 } = useScroll();
- scrollX, scrollY : 절대 스크롤 위치값 [px]
- scrollXProgress, scrollYProgress : 상대 스크롤 위치값 (0~1)
- SVG Animation
- <path>
- 'fill' 속성 : svg의 색깔을 변경 가능
- 'fill="currentColor"' : <svg>의 색상을 사용하며, 기본값은 'black'
- <svg>의 'color'속성을 통해 변경 가능
- 'fill="transparent"' : 투명
- 'fill="currentColor"' : <svg>의 색상을 사용하며, 기본값은 'black'
- 'stroke' 속성 : 테두리의 색깔을 변경 가능
- 'strokeWidth' 속성 : 테두리의 두께를 변경 가능
- 'stroke', 'strokeWidth', 'fill' 등은 CSS로 옮길 수 있음
- 'fill' 속성 : svg의 색깔을 변경 가능
- SVG를 animate하기 위해 <motion.path>로 대체하여 사용
- 'pathLength' 속성 : 현재 위치까지의 path의 길이를 나타냄 (0~1)
- 이를 사용해 테두리를 그려주는 animation 사용 가능
- 'pathLength' 속성 : 현재 위치까지의 path의 길이를 나타냄 (0~1)
- <path>
- 특정 프로퍼티의 transition 시간을 정하는 방법
- 기본적으로 전체 속성의 animation 시간이 통일되어 있었음
- 각각의 프로퍼티마다 duration이나 delay 시간을 지정할 수 있음
- 사용법 : transition에서 바꾸고자 하는 프로퍼티에 직접 할당
- 전체에 대한 animation은 'default'에 할당
- ex. transition : { default : {duration : 5}, fill : {duration : 1} }
- AnimatePresence
- React에서 사라지는(없어지는) 컴포넌트를 animate할 수 있도록 함
- 기본 React에서는 사라지는 컴포넌트를 animation을 부여할 수 없음
- 규칙
- <AnimatePresence>는 항상 'visible' 상태이어야 함
- <AnimatePresence>의 내부에는 조건문이 존재해야 함
- 기본형 : <AnimatePresence>{조건 ? 참 : 거짓}</AnimatePresence>
- 조건문에 들어가는 컴포넌트에 animation을 적용함
- 컴포넌트가 사라질 떄의 animation은 'exit' 속성을 사용
- 컴포넌트에 'custom' 속성값을 넣어, variants에서 조건문 사용 가능
- <motion.태그>와 <AnimatePresence> 둘다 'custom' 속성을 부여하여 사용
- 'variants'를 Object를 return하는 콜백함수로 사용해야함
- ex. <AnimatePresence custom={isBack}> <Box custom={isBack} ... /> </AnimatePresence> const boxVariants = { entry : (isBack: Boolean) => ({ x : isBack ? -500 : 500; }), };
- <AnimatePresence>의 'mode="wait"' 프로퍼티
- exit가 일어난 후 entry가 일어나도록 설정하는 프로퍼티
- 미 사용 시 exit와 entry가 동시에 일어남
- React에서 사라지는(없어지는) 컴포넌트를 animate할 수 있도록 함
- Motion Value
- 23-09-15 : #8.14 ~ #9.4 / Animations(3)
- Layout Animation
- 컴포넌트에 'layout' 속성을 부여 시 CSS에의해 해당 컴포넌트의 layout이 바뀔 때 마다 자동으로 animation이 만들어짐
- 기본형 : <컴포넌트명 layout />
- Shared Layout Animation
- 서로 다른 컴포넌트에 같은 값을 가지는 'layoutId' 속성을 부여 시 하나의 컴포넌트로 연결하여 animation을 보여줌
- 시각적으로 하나의 연속 컴포넌트로 처리됨
- 기본형 : <컴포넌트명 layoutId="값" />
- 서로 다른 컴포넌트에 같은 값을 가지는 'layoutId' 속성을 부여 시 하나의 컴포넌트로 연결하여 animation을 보여줌
- Layout Animation
- 23-09-19 : #9.0 ~ #9.1 / NETFLIX Clone(1) - Setup
- Font 파일 적용
- .woff2, .ttf 등의 font파일 적용 시 'src'폴더 내에 파일을 위치시켜야 함
- '@font-face'문을 통해 font를 정의
- 'globalStyle' 보다는 'css파일'에 정의해야 초기 로딩 성능이 향상됨
- Font 파일 적용
- 23-09-21 : #9.2 / NETFLIX Clone(2) - Header
- [Framer-Motion] Animation 반복
- CSS의 값을 배열형식으로 지정 시 자동으로 값을 변환하는 Animation처럼 작동함
- 'transition'의 'repeat'프로퍼티를 사용해 Animation 반복 횟수 지정 가능
- number, "Infinity" 등
- [React-Router-Dom] useMatch()
- useMatch(URL주소) : 현재 페이지가 어디에 위치하는지 알려주는 Hook
- 현재 주소와 같을 시 Object를 반환
- 현재 주소와 다를 시 'null'값을 반환
- 상대 경로, 절대 경로 둘다 사용 가능
- useMatch(URL주소) : 현재 페이지가 어디에 위치하는지 알려주는 Hook
- [Framer-Motion] Animation 반복
- 23-09-22 : #9.3 ~ #9.8 / NETFLIX Clone(3) - Header & Home
- [CSS] 'transform-origin' : 변화가 시작하는 위치를 지정하는 속성
- 기본형 : transform-origin: 세로 가로;
- [Framer-Motion] 함수로 animation 제어하기
- useAnimation() : animation의 제어를 함수로 제어하도록 함
- 기존에는 컴포넌트에 속성을 부여하였음
- 여러 개의 animation을 동시에 실행시키고 싶을 때 유용함
- 기본형 선언 : const 변수명 = useAnimation(); 사용 : 변수명.프로퍼티({스타일}) 적용 : <컴포넌트명 animate={변수명} />
-
const inputAnimation = useAnimation(); const toggleSearch = () => { if (searchOpen) { inputAnimation.start({ scaleX: 0 }); } else { inputAnimation.start({ scaleX: 1 }); } setSearchOpen((prev) => !prev); }; <Input initial={{ scaleX: 0 }} animate={inputAnimation} />
- 'useMotionValueEvent()' 메서드를 통한 제어로, variants 사용도 가능
- useAnimation() : animation의 제어를 함수로 제어하도록 함
- [React-Query] 영화 API
- 'TMDB'사이트로부터 영화 API를 사용
- React-Query 사용법
- 'query client'를 만들고, <QueryClientProvider>로 감싸주기
- fetcher함수 정의하기
- 'useQuery()'를 사용해 API 데이터 가져오기
- 기본형 : const { isLoading, data, error } = useQuery<제네릭>([쿼리키명], fetcher함수, ?옵션);
- 받은 데이터의 타입 설명하기
- 'interface'를 사용해 데이터타입 정의
- [Framer-Motion] 빠른 시간 내의 연속된 animation 중첩 현상 문제
- <AnimatePresence>의 'onExitComplete'속성은 exit가 끝난 후 실행됨
- animation이 실행되는 동안 동작을 막도록 함
- <AnimatePresence>의 'onExitComplete'속성은 exit가 끝난 후 실행됨
- [Framer-Motion] 최초 렌더링 시의 animation 해제
- <AnimatePresence>의 'initial'속성값을 'false'로 줄 시 최초 렌더링 시의 animation을 해제함
- 영화 리스트에 영화들 넣기
- 영화리스트 배열을 슬라이더 배열의 갯수(offset)만큼 잘라서 여러 페이지(page)를 만들어야 함
- 배경으로 사용한 첫 번째 인덱스는 제외 : data?.results.slice(1);
- '배열.slice(시작인덱스, 끝인덱스)' 메서드를 사용해 배열을 잘라서 사용
- '배열.slice(offset*page, offset*page+offset);'을 사용하고, page를 1씩 증가
- 영화리스트 배열을 슬라이더 배열의 갯수(offset)만큼 잘라서 여러 페이지(page)를 만들어야 함
- [CSS] 'transform-origin' : 변화가 시작하는 위치를 지정하는 속성
- 23-09-23 : #9.9 ~ #9.10 / NETFLIX Clone(4) - Box animations
- [CSS] 영화 리스트에서 영화를 hover 시 scale을 커지게 할 때, 양 끝에 존재하는 영화가 화면이 잘리는 현상
- 첫 번째, 마지막 요소에 'transform-origin' 속성을 사용
- [CSS] 영화 리스트에서 영화를 hover 시 scale을 커지게 할 때, 양 끝에 존재하는 영화가 화면이 잘리는 현상
- 23-09-25 : #9.11 ~ #9.15 / NETFLIX Clone(5) - Movie modal & Search Form
- 23-09-26 : NETFLIX Clone(6)
- Update : [Header] 검색창을 열 시 자동으로 입력창에 focus
- 23-09-27 : NETFLIX Clone(7)
- Update
- [Header]
- 검색창 바깥을 클릭 시 열려있는 검색창을 닫도록 함 + 닫을 시 입력된 내용 초기화
- 검색 기능 업데이트
- 검색창에 값이 있을 시에만 검색값을 비울 수 있는 'x'버튼 생성
- 검색 조건 미달 시 error를 보여주는 message 생성
- [Search]
- API 결과값의 interface 정의
- 인물 검색 시 관련 작품을 '.map()'을 통해 풀어서 화면에 보여줌
- 영화, tv쇼 등 여러 API를 각각 사용할 필요없이 하나의 API 사용으로 해결
- [Header]
- Fix
- [Header] 검색창이 열릴 시 우측 부분이 form에 가려져 input이 클릭이 안 되는 현상 수정
- [Search] 검색 시 동일 작품이 중복되는 현상 수정 (중복 결과 제거)
- 멀티 검색이기 때문에, 작품/인물 검색으로 인해 중복되는 것으로 추정
- 중복 시 하나만 보여주도록 수정
Issue : [Search] 장르 검색 관련 설정하기
- Update
- 23-09-28 : NETFLIX Clone(8)
- Update : [Search] 검색 UI 업데이트 & 포스터 이미지가 없는 작품의 대체 이미지
- Fix : [Header] 검색창의 검색 키워드가 우측의 'x'버튼과 겹치는 현상 수정
Issue : [Search] 검색 결과의 갯수
- 23-09-29 : NETFLIX Clone(9)
- Update : [Search] 아이템 hover 시의 infoBox 업데이트
- Fix : [Search] 검색 결과의 갯수
- 23-10-02 : NETFLIX Clone(10)
- Update
- [Slider] 슬라이더 좌/우 버튼 생성 및 애니메이션 업데이트
- [Banner] 영화/TV 둘 다 사용 가능하도록 업데이트
- Fix : [Modal-Box] z-index 수정
- Update
- 23-10-04 : NETFLIX Clone(11)
- Fix : [Slider] absolute인 자식 요소의 height를 부모 요소의 height에 적용(padding-bottom 사용)해 슬라이더 좌/우 버튼의 높이를 같게 만듦
- Update : [Slider] hover 시 infoBox / click 시 infoBox 기초작업
- 23-10-05 : NETFLIX Clone(12)
- Update
- [Modal-Box]
- 데이터 추가 및 UI 업데이트
- Nested-Router 분할 정복
- 홈에서 이미 API data를 가지고 있다면 바로 사용 / URL 검색 시 API 검색
- [Modal-Box]
Issue : [Modal-Box] URL 직접 입력 시 404 Error 해결하기
- Update
- 23-10-08 : NETFLIX Clone(13)
Issue : [Modal-Box] 스크롤바 문제
- 23-10-11 : NETFLIX Clone(14)
- Fix : [Modal-Box]
- recommendationData가 있을 경우 스크롤바가 생기지 않는 문제 해결
- 상위 컨테이너 <Movie>에게 'recommendationData?.result.length'에 따라 참일 경우, 'height:100%'를 선언
- URL 직접 입력 시 404 Error 문제 해결
- detail과 credit API data가 없을 시 화면을 보여주지 않게 조건문 재설정
- recommendationData가 있을 경우 스크롤바가 생기지 않는 문제 해결
- Update
- [Modal-Box] 추천 페이지 업데이트
- [Slider] 분할정복
- Fix : [Modal-Box]
- 23-10-12 : NETFLIX Clone(15)
- Update
- [Slider]
- 슬라이더 타이틀 추가
- 첫 슬라이더만 2번째 데이터부터 보여줌 (첫번째 데이터는 Banner로 사용)
- [Modal-Box] movie, tv 둘 다에서 모달박스가 나오게 업데이트
- [Home, TV] 더 많은 슬라이드 업데이트
- [Footer] 업데이트
- [Slider]
- Fix : [Slider] 각기 다른 슬라이더에서 같은 영화가 있을 시 서로 애니메이션을 간섭하는 현상 수정
- 'LayoutId'가 중복되지 않도록 수정
- Update
- 23-10-13 : NETFLIX Clone(16)
- Update
- [Banner] 재생 버튼, 상세 정보 버튼 업데이트
- [Item] 재생 버튼 클릭 시 예고편 영상(YouTube) 보여주기 업데이트
- Update
- 23-10-16 : NETFLIX Clone(17)
- Fix
- [Info-Box] hover 시 하단의 슬라이드보다 레이어가 뒤에 있는 현상 수정
- [Iframe] 정가운데 정렬
- Update
- [ClickedItem] 영화와 tv를 한 컴포넌트로 통합
- [Search] 검색된 item 클릭 시 modal-box 보여주기
- Issue : [Search] 검색된 item의 modal-box에서 recommendItem 클릭 시 URL 이동하는 현상
- 검색 시 검색어를 Query String 대신 하위 동적URL 및 nested route 사용?
- Fix
- 23-10-17 : NETFLIX Clone(18)
- Fix : [Search] 검색된 item 클릭 시 overlay 위치 수정
- 23-10-18 : NETFLIX Clone(19)
- Fix
- [Iframe] 중복된 key값을 가지는 현상 수정
- [Modal-Box] recommend item들의 height값 수정 (max-height)
- Update : [TV, Modal-Box] Season 및 Episode 업데이트 (1/2)
- API 가져오기 및 전체적인 큰 틀 제작
- Issue : [TV, Season] select svg 애니메이션 만들기
- Fix
- 23-10-20 : NETFLIX Clone(20)
- Update
- [Modal-Box] 스크롤바 기능을 유지하면서, 화면에 숨기기
- [TV, Modal-Box] Season 및 Episode 업데이트 (2/2)
- 세부사항 꾸미기
- 사진이 없을 시 텍스트로 대체
- 처음 10개 까지만 보여주고, 버튼 클릭 시 해당 시즌의 에피소드 다 보여주기
- [Head] <title> 업데이트
- Update
- 23-10-21 : NETFLIX Clone(21)
- Update : [Head] favicon 업데이트
- Fix
- [Head] 'description' 변경
- [Banner] 배너 이미지 중앙으로 정렬
- [Slider] 버튼 색깔 변경
- [Footer] github 링크 및 'MenuBox'의 <li>의 width 수정
- To-Do
- 'swiper.js' 패키지의 슬라이더 알아보기
- [Head] meta미리보기(썸네일) 업데이트
- [Season] svg 애니메이션 고치기
- [Modal-Box] footer 및 관람 등급 업데이트
노마드 코더 정책 상 강의요약은 괜찮으나, 코드와 필기는 공개적인 곳에 올리면 안 됨.
필기 요약지는 암호화된 .zip 파일로 저장함.