일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 클래스
- 노마드코더
- 논리연산자
- 웹개발
- OOP
- 상속
- REACT
- 캡슐화
- JavaScript
- Hooks
- frontend
- typeScript
- 객체지향프로그래밍
- 리액트
- Fetch
- 자바스트립트
- webdevelopment
- 불변성
- Props
- 타입스크립트
- 부트캠프
- Zustand
- 추상화
- 투두앱만들기
- js
- github
- 패스트캠퍼스
- 프론트엔드
- CSS
- 자바스크립트
- Today
- Total
connecting dots
Beginner 14회차 (8/20) | TS 유틸리티 타입, React-Router의 페이지 지정 방법, 모달 애니메이션 적용 실습, todo 순서 바꾸기 실습(sortablejs), useRef와 current 속성 본문
Beginner 14회차 (8/20) | TS 유틸리티 타입, React-Router의 페이지 지정 방법, 모달 애니메이션 적용 실습, todo 순서 바꾸기 실습(sortablejs), useRef와 current 속성
dearsuhyun 2024. 8. 21. 14:02TS 유틸리티 타입
객체 데이터에 있는 모든 내용을 선택적으로 만듬
interface User {
name: string
age: number
}
const user: User {
name: 'suhyun'
}
// 오류 발생
// 'age: 85' 없으면 필수인데 없기 때문에 오류 !
Partial을 붙여주면 interface 내용이 필수적이 아니라 선택적으로 설정된 것과 같이 작동 !
user에서 name, age를 사용하지 않아도 오류가 발생하지 않음
'처음부터 선택적으로 만들면 안되는가 ?'
--> 모든 것에 필수여야 하는 경우에 대응하기 힘듬
만들 때는 필수 --> 선택적으로 ? 붙여서 사용하는 것이 일반적 !
interface PartialUser {
name?: string
age?: number
}
// utility type (TS에 이미 내장된 타입)
const user: Partial<User> {
name: 'suhyun'
}
코드 적용
- record
key를 속성(key)로, type을 그 속성값의 type으로 지정하는 새로운 타입
Record<KEY, TYPE>
type TName = 'neo' | 'lewis'
const developers: Record<TName, number> = {
neo: 12,
lewis: 13
}
이렇게 이해할 수 있음
interface INewType {
neo: number
lewis: number
}
- omit
TYPE에서 KEY로 속성을 생략하고 나머지를 선택한 새로운 타입을 반환
TYPE은 속성을 가지는 인터페이스나 객체 타입이어야 함
Omit<TYPE, KEY>
interface IUser {
name: string
age: number
email: string
isValid: boolean
}
type TKey = 'name' | 'email'
const user: Omit<IUser, TKey> = {
age: 22,
isValid: true,
name: 'Neo' // TS2322: Type '{ age: number; isValid: true; name: string; }' is not assignable to type 'Pick<IUser, "age" | "isValid">'.
}
이렇게 이해할 수 있음 !
interface INewType {
// name: string
age: number
// email: string
isValid: boolean
}
- exclude
유니언 TYPE1에서 유니언 TYPE2를 제외한 새로운 타입을 반환
Exclude<TYPE1, TYPE2>
type T = string | number
const a: Exclude<T, number> = 'Only string'
const b: Exclude<T, number> = 1234 // TS2322: Type '123' is not assignable to type 'string'.
const c: T = 'String'
const d: T = 1234
todo 추가 기능이 구현되지 않는 문제
기존 코드
async function createTodo() {
await axios.post('/api/todos'), {
method: 'POST',
data: {
title
}
}
getTodos()
}
수정 코드
method, data 부분을 axios의 두번째 인수로 줘야 하는데 그렇지 못해서 발생한 오류 수정
async function createTodo() {
await axios.post('/api/todos', {
method: 'POST',
data: {
title
}
})
getTodos()
}
수정 후 main에 푸시하면 vercel에서 자동으로 배포 !
React-Router의 페이지 지정 방법
1. 객체 형식으로 페이지(라우트) 지정
export const router = createBrowserRouter([
{
path: '/',
element: <Main />,
// 메인 페이지가 보이는 상태에서 모달을 보여줄거니까 children으로 설정
children: [
{
path: ':todoId',
element: <TodoItemDetails />
}
]
}
])
2. 컴포넌트 방식으로 페이지(라우트) 지정
export default function Index() {
// location 객체는 현재 URL에 대한 정보를 가지고 있음
const location = useLocation()
return (
<AnimatePresence mode="wait">
<Routes
location={location}
key={location.pathname}>
<Route
path="/"
element={<Main />}>
<Route
path={'/:todoId'}
element={<TodoItemDetails />}
/>
</Route>
</Routes>
</AnimatePresence>
)
}
모달 애니메이션 적용 실습
routes > index.tsx
<AnimatePresence> 전체 주소의 사라지는 애니매이션 까지 담당하겠다 !
페이지를 바꾸는 방법으로 모달을 사용하고 있기 때문에 페이지 사라질 때 부분도 설정해주어야 함
모달 사라지게 할 때 주소가 바로 사라지니까 당연히 모달도 바로 사라지는 것 --> AnimatePresence 사용
todoItemDetails.tsx
나타날 때는 자연스럽게 나타나지만, 끌 때는 바로 꺼짐 (페이지를 바꿔서 모달을 띄우는 것이기 때문)
exit={{ opacity: 0}}을 추가해서 사라질 때도 자연스럽게 사라지도록 만들어주기 !
구현 화면
todoList에서 item 순서 바꾸기 실습
import Sortable from 'sortablejs'
npm i -D @types/sortablejs
useRef과 current 속성
Main.tsx
Sortable의 필수 속성 4가지
new Sortable(listRef.current, {
handle: '',
animation: 0,
forceFallback: true,
onEnd: () => {}
}
new Sortable(todoListEl.current, {
handle: '.drag-handle', // 드래그 핸들이 될 요소의 선택자를 입력
animation: 0, // 정렬할 때 애니메이션 속도(ms)를 지정, default: 150
forceFallback: true, // 크로스 브라우징, 다양한 환경의 일관된 Drag&Drop(DnD)을 위해 HTML5 기본 DnD 동작을 무시하고 내장 기능을 사용, default: false
// 요소의 DnD가 종료되면 실행할 핸들러(함수)를 지정
onEnd: event => {
const { oldIndex, newIndex } = event
if (oldIndex === undefined || newIndex === undefined) return
console.log('oldIndex:', oldIndex, 'newIndex:', newIndex)
mutate({
oldIndex,
newIndex
})
}
sortablejs는 화면만 바꿔주기 때문에 새로고침하면 순서 바꾼 것이 그대로 돌아옴
서버에 전송해줘서 새로고침해줘도 유지하도록 ! api 사용해주어야 함
API 명세서 확인
store에 reordertodos 생성
* TS 유틸리티 타입 자주 쓰이는 4가지는 꼭 알아두기 (다른 것도 읽어보기)
partial, record, omit, exclude
* Pakage.json
Sem Ver: ^35.2.4
--> major 버전은 바뀌지 않지만, 버셀 패키지를 설치하면 마이너와 패치 버전을 가장 최신으로 유지한다
"vercel": "^35.2.4",
// latest(최신버전) npm i -D vercel@latest // canary(배타버전) npm i -D vercel@canary
* transition: 전 상태 --> 후 상태를 자연스럽게 전환해준다
* 처음부터 react-** 라고 만들어진 라이브러리는 대안이 없음
sortablejs 의 경우 react-sortablejs라는 대안이 있는 것임
순수 js(ts)로 만들어진 라이브러리가 있다면 react-**잘 사용하지 않는 이유 ?
--> react, vue, svelte같은 프레임워크는 계속 변화함 ==> react-**도 업데이트 되지 않으면 사용 불가
라이브러리에 의존해서 만들어진 추가적인 라이브러리는, 라이브러리가 망가지면 쓸 수 없음
순수 js, ts로 만들어진 라이브러리를 사용하는 것을 추천함 !
https://www.heropy.dev/p/WhqSC8
https://github.com/ParkYoungWoong/todo_vite-react-ts
https://sortablejs.github.io/Sortable/#frameworks