connecting dots

Beginner 10회차 (8/8) | 모달 기능 구현 실습, z-index, 리액트 라우터 탐색 방식, React Hooks (useNavigate, useParams), Link, zustand로 상태관리 실습 본문

Live Class/Beginner

Beginner 10회차 (8/8) | 모달 기능 구현 실습, z-index, 리액트 라우터 탐색 방식, React Hooks (useNavigate, useParams), Link, zustand로 상태관리 실습

dearsuhyun 2024. 8. 11. 14:18

모달 CSS

 

.modal {

  position: fixed --> 화면 전체를 덮어야 할 때(화면을 기준으로)

  width: 100vw --> 화면의 가로너비 100%,

  height: 100vh --> 화면의 세로너비 100%

}

.overlay {

  position: absolute --> 부모요소인 modal을 기준으로

  (position을 갖는 것이 우선순위를 갖는다 !)

  width: 100% --> 뷰포트 쓰지 않아도 됨. 부모요소에 영향을 어차피 받기 때문에



.contens {

  calc(100vh-40px) --> 전체 뷰포트 height에서 위아래 20px씩 공간 남겨놓겠다

  overflow: auto --> 자동으로 넘치면 스크롤

}

 

z-index

- position이 설정된 element에서만 의미를 가짐

- 더 높은 숫자를 가진 element가 더 높은 우선순위를 가짐

position

- absolute: 부모 요소를 기준으로 배치 (부모는 relative로 해주는 것이 관례)

- sticky: 뷰포트를 기준으로 배치

- relative: 요소의 원래 위치를 기준으로 상대적으로 배치

 

React Hooks

useNavigate

useNavigate 훅은 프로그래밍 방식으로 페이지를 이동할 수 있도록 해줌

사용자가 버튼 클릭이나 특정 이벤트 발생 시 다른 페이지로 이동하도록 할 때 유용

URL을 변경하지 않고 페이지 이동만 수행 !

 

import { useNavigate } from 'react-router-dom'

export default function TodoItemModal() {
  const navigate = useNavigate()
  ///
}

function offModal() {
    navigate('/')
  }
  
<div
    className={styles.overlay}
    onClick={offModal}>
</div>

 

--> overlay영역을 클릭할 경우 offModal()이 실행되고 랜딩 페이지로 이동 !

 

useParams

모달을 띄울 때 각 내용에 맞는 모달을 띄워줘야 되겠네 ? --> useParams 사용

useParams 훅은 URL 경로에서 동적 파라미터를 추출하는 데 사용됩니다. 주로 동적 라우팅을 처리할 때 유용합니다.

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

const { todoId } = useParams() // URL 경로에서 todoId 파라미터를 추출 (routes -> index.tsx에 정의된 id)

const todos = useTodosStore(state => state.todos)
const currentTodo = todos.find(todo => todo.id === todoId) // 현재 todoId에 해당하는 할 일을 찾음

todoId (주소)에 맞는 내용이 나오고 있음

 

1. URL 경로에서 파라미터 추출:

useParams 훅을 호출하면 현재 URL 경로에서 동적 파라미터를 추출하여 객체 형태로 반환합니다.

예를 들어, 경로가 /todo/123일 때 useParams{ todoId: '123' } 객체를 반환합니다.

이 예제에서 :todoId는 URL 경로에서 동적으로 설정된 부분입니다.

 

2. 파라미터를 컴포넌트에서 사용:

const { todoId } = useParams();를 통해 URL에서 추출된 todoId 파라미터를 변수로 사용합니다.

이를 통해 todoId를 이용하여 전역 상태의 할 일 목록에서 특정 할 일을 찾을 수 있습니다.

 

<Link> 컴포넌트

HTML의 <a>와 같은 역할

클릭하면 다른 페이지(to="")로 이동할 수 있게 해줌

URL이 변경됨

// <Link to="이동할 페이지"> = <a href="">
// title을 클릭하면 todo.id에 대한 페이지로 이동

<Link to={`/${todo.id}`}>{todo.title}</Link>

URL이 변경되는 모습을 볼 수 있음

 

 

--> Link 컴포넌트를 사용해도 개발자도구를 열어보면 결국 <a> 태그로 변환됨. 하지만 리액트 라우터가 a태그로 이동하는 것을 어느정도 제어해주기 때문에 Link 사용 !

 

리액트 라우터 탐색 방식 (페이지 이동 방식)

1) 컴포넌트 방식의 탐색: <Link> 컴포넌트 사용

<Link to=""/>

 

2) 프로그래밍 방식의 탐색

사용 예시)

- 함수에서 다른 코드를 같이 실행할 때 (메인페이지 이동 이외에 다른 기능도 함께할 때)

function offModal() {
  console.log('off modal !')
  /// ~
  navigate('/')
}

 

- 추상화를 시켜주고 싶을 때 

navigate( '위치' )

 

언제 어떤 방식을 사용해야 할까 ? 적절히 취사 선택

--> 밑 예제에서는 link 태그를 이용하는 컴포넌트 방식을 사용했을 때

추상화가 되어있지 않아서 오버레이 부분을 클릭하면 모달을 끈다는 함수 내용을 알 수 없음

이런 경우에는 프로그래밍 방식을 사용하는 게 더 좋을 수 있다 !

 

상태관리의 필요성

출처: 실시간 수업

zustand

리액트 프로젝트에서 사용하는 상태관리 라이브러리

Redux보다 덜 복잡하고 사용하기 편리함.

npm i zustand

 

zustand 이해하기

import { create } from 'zustand'

const useStore = create((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

function Counter() {
  const { count, inc } = useStore()
  return (
    <div>
      <span>{count}</span>
      <button onClick={inc}>one up</button>
    </div>
  )
}

 

 

1. 스토어 생성

const useStore = create((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

 

create 함수는 Zustand 스토어를 생성하는 데 사용됩니다.

set 함수는 상태를 업데이트하는 데 사용됩니다.

count: 상태의 초기 값입니다.

inc: count 값을 1 증가시키는 함수입니다. set 함수를 사용하여 상태를 업데이트합니다.

 

2. 컴포넌트에서 상태 사용

function Counter() {
  const { count, inc } = useStore()
  return (
    <div>
      <span>{count}</span>
      <button onClick={inc}>one up</button>
    </div>
  )
}

 

useStore 훅을 사용하여 Zustand 스토어에서 상태와 함수를 가져옵니다.

count: 현재 상태 값입니다.

inc: count 값을 1 증가시키는 함수입니다.

count 값을 화면에 표시하고, 버튼을 클릭하면 inc 함수를 호출하여 count 값을 증가시킵니다.

 

함수 이해

일반 함수와 화살표 함수를 왜 구분해야 할까 ?

--> this 키워드를 사용하는 방법이 완전히 다르기 때문 !!! ★

 

상태관리 실습

store 생성

create 함수는 store를 생성하는 함수 !

 

- store에 있는 속성(property) = 상태(state)

todos: [] as Todos,
message: '',
loading: true

 

- store에 있는 메소드(method) = 액션(action)

function (set) {}

 

 

combine함수는 Zustand의 미들웨어로, 상태 객체와 액션 함수를 결합하여 하나의 상태 스토어를 생성할 수 있게 해줌.

이는 상태와 액션을 별도로 정의하고, 이를 하나의 스토어로 합치는 데 유용함.

타입스크립트를 사용할 때 상태 타입을 직접 작성하지 않고 추론하도록 combine 미들웨어를 사용할 수 있음

combine (상태객체, 액션함수)

 

// 기본
create(set => ({상태1, 상태2, 액션1, 액션2}))

// 기본 + 타입
create<타입>(set => ({상태1, 상태2, 액션1, 액션2}))

// combine 미들웨어 사용법
1) create(combine(상태객체, 액션 함수))
2) create(combine({상태1, 상태2}, set => ({액션1, 액션2})))

 

상태객체 부분

 

--> combine에서 타입 추론이 되는 것은 두고, 되지 않는 것만 단언해주면 됨

여기서 todos는 타입 단언을 해주지 않으면 naver 타입으로 인식하게 됨 !

 

set 매개변수는 상태를 갱신하는 함수
매개변수의 유효범위는 combine 함수의 두 번째 인자인 객체 안에서만 유효함.
setTodos는 todos를 갱신하는 함수였음. 이제는 store에서 상태 관리를 하기 때문에 setTodos가 아니라 set으로 바꿔줘야 함.

액션함수 부분

 

--> 만든 store를 Main.tsx로 import해서 사용 !

 

todoItemModal.tsx에서 store 데이터 사용 !

 

createdAt은 일반적으로 객체의 생성 시간을 나타내는 속성입니다. 이는 데이터베이스나 백엔드에서 객체가 생성된 시점을 기록하기 위해 자주 사용됩니다. 예를 들어, 특정 할 일(todo) 항목이 생성된 시간을 저장하기 위해 createdAt이라는 속성을 추가할 수 있습니다.

 

구현 모습

 


* <h1> 태그는 페이지에 딱 하나만 있는 것이 좋음. html은 시멘틱 방식으로 만들기 때문.

* 팝업과 모달의 차이: 주변을 같이 제어할 수 있느냐 없느냐의 차이 !

* 지금 단계에서는 편리함보다는 하드코딩 등 물리적으로 많이 연습해보기

* css에서 색상은 이름으로 쓰지말고 # 코드로 쓰기
position이 있는게 우선순위를 가짐
position이 있어야 하긴 하는데 .. 값만 필요할 때 relative 사용
absolute, fixed는 정확한 필요가 있어야 쓰는 것

* module 방식
TodoItemModal.module.css 파일 만들어서
className={styles.modal} 이렇게 연결

* 에러 생겨서 1-2시간 삽질해보는 건 좋은 경험 ^_^

* 아울렛을 쓸 때는 부모 페이지 (컴포넌트)에서 자식 페이지 (컴포넌트)를 렌더링 할 위치를 지정하는 것

 

 

https://vuetifyjs.com/en/components/dialogs/#usage

 

Dialog component — Vuetify

The dialog component informs a user about a specific task and may contain critical information or require the user t...

vuetifyjs.com

https://www.heropy.dev/p/n74Tgc

 

Zustand 핵심 정리

Zustand(주스탠드)는 작고 빠르며 확장 가능한 React 프로젝트에서 사용하는 상태 관리(Store) 라이브러리입니다.

www.heropy.dev

https://developer.mozilla.org/ko/docs/Web/CSS/z-index

 

z-index - CSS: Cascading Style Sheets | MDN

CSS z-index 속성은 위치 지정 요소와, 그 자손 또는 하위 플렉스 아이템의 Z축 순서를 지정합니다. 더 큰 z-index 값을 가진 요소가 작은 값의 요소 위를 덮습니다.

developer.mozilla.org

https://www.daleseo.com/css-position/

 

CSS의 5가지 position 속성 값 기본 정리

Engineering Blog by Dale Seo

www.daleseo.com

 

반응형