[redux 2탄] Redux 공부는 내가 했는데, 미니 프로젝트는 누가할래?

const job = '프론트엔드';·2023년 8월 17일
0

나지..

https://gazero-marvel.netlify.app/

Redux를 사용해서 간단한 Card App을 만들기

사용스택 및 라이브러리(React)

npx create-react-app card-app

npm install react-redux redux
npm install react-router-dom
npm install styled-components

npm start
  • react-redux & redux
  • react-router-dom
  • styled-components

🖥 화면구성(엄청 간단함 주의)

✅ 메인

  1. 상단바
  2. 카드섹션

✅ 디테일 페이지


  1. 상단바(상동)
  2. 디테일 컨텐츠 섹션
    2-1. Title
    2-2. Video
    2-3. Description
    2-4. Back Button

리덕스와 리액트 라우터 돔을 사용함

1. CreateStore

  • 이번에는 별도의 파일을 만들어서 상태를 관리함
  • contents.js 파일에 CreateStore를 import해줌
import { createStore } from "redux";

2. reducer 함수 만들기

function reducer(state, action) {
  return { contents };
}
  • 현재상태와 action을 담았음
  • 그리고 contents로 리턴함
  • action의 짝꿍 type이 없음 왜? 수정이나 삭제 기능을 하지 않을 것이기 때문(= useDispatch 안쓰겠다)

3. 저장고에 넣어둠

export const store = createStore(reducer);

4. contents가 뭐길래 reducer함수가 리턴하는 거지?

 const contents = [ 
   {
    path: "/",
    imagePath: "",
    hoverImagePath: "",
    title: "",
    detail: {
      name: "",
      korName: "",
      videoSrc: "",
      desc: "",
    },
  },
 ]
  • 사용할 데이터가 배열 형태로 담겨있음
  • 그러니깐, Redux상태 관리를 이용해서 contents에 있는 상태를 가져다 쓰겠다는 의미

5. Provider로 감싸주기

import { Provider } from "react-redux";
import { store } from "./utilities/contents";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);
  • 다른 자식 컴포넌트들이 다 사용할 수 있도록 가장 상위 컴포넌트인 App컴포넌트를 감싸서 store에 저장고(store)를 담아 넘겨줌

🌼리덕스 사용할 준비 끝🌼 리덕스만 끝남. 리액트 라우터 돔 남았음.

6. 리액트 라우터 돔(react-router-dom) import

import { BrowserRouter, Route, Routes } from "react-router-dom";
  • 화면이 실제로 뿌려지는 컴포넌트에 감싸줌(여기에서는 App.js)
   <BrowserRouter>
   	<Routes>
     <Route />
     <Route />
     <Route />
     ....
     <Route />
    </Routes>
   </BrowserRouter>
  • 이런 식으로 감싸줌
  • App.js에는 상단바, 카드가 뿌려지는 섹션 두가지로 구분됨
  • 하지만 카드를 누르면 각각의 카드마다 개별적으로 상세페이지가 주어진다는 특징이 있음
  • 따라서 라우트 될 필요가 없는(상세페이지에서도 동일한 상단바를 사용하기 때문) 상단바는 Routes내부에서 제외됨
   <BrowserRouter>
    <상단바 />
   	<Routes>
     <Route 카드1 상세페이지 />
     <Route 카드2 상세페이지/>
     <Route 카드3 상세페이지/>
     ....
     <Route 카드9 상세페이지/>
    </Routes>
   </BrowserRouter>
  • 이런 형태로 만들어 줄 수 있음
  • 또한, 카드는 배열 형태로 데이터를 담아둔 contents에 저장되어 있기 때문에 map으로 돌려서 카드를 배열 순서대로 나열해줌

✅ useSelector로 contents의 상태를 받아옴(feat.map)

    <BrowserRouter>
      <GlobalStyles />
      <상단바>
      </상단바>
      <Routes>
        {useSelector((state) => state.contents).map((content, idx) => {
          return (
            <Route
              path={content.path}
              key={idx}
              element={<Detail content={content.detail} />}
            />
          );
        })}
        <Route path="/" element={<Cards />} />
      </Routes>
    </BrowserRouter>
  • useSelector를 통해서 상태를 받아오고, 상태의 contents배열을 map으로 돌림
  • contents에서는 path, idx를 받아옴
  • 그리고 content.detail을 담아서 자식 컴포넌트인 Detail에 넘김

리액트 라우터 돔을 사용하는 이유?🖐️

  • 보통 페이지 주소에 따라 해당페이지로 이동하면 페이지 화면이 로드되면서 html이 뿌려지는 구조
  • 페이지 전환 순간에 '번쩍'하는게 있음
  • 하지만 라우터 돔을 사용하면?
  • SPA에서 렌더링만 됨
  • 속도가 훨씬 빠르고, 여러개의 주소를 할당할 필요도 없음

✅ Detail 컴포넌트

  • useSelector로 저장고에 담긴 데이터를 사용하겠다고 선언
  • 디테일 페이지는 데이터가 많이 사용됨
  1. detail.name
  2. detail.korName
  3. detail.viedoSrc
  4. detail.desc
  • 하지만 모두 content로 받아오기 때문에(contents가 아닌, content인 이유? 부모 컴포넌트에서 넘겨줄때 content.detail을 넘겨받음)
  • 경로는 content.detail.name 형태로 받아 와야함
  • 뒤로가기 버튼을 위해 useNavigate()를 사용
 const navigate = useNavigate();

 <BackButton onClick={() => navigate(-1)}>BACK</BackButton>
  • 뒤로가기 버튼을 누르면 onClick이벤트를 통해 이전 페이지로 이동

✅ Cards 컴포넌트

  • 카드를 구성하는 상세 정보들이 담겨있음
  • useSelector()를 사용해서 상태를 받아옴
  • NavLink를 통해서 각각 카드의 경로를 지정함
   <NavLink to='/path' />
  • 이런식으로 사용

핵심적인 리덕스와 리액트 라우터 돔의 구조 및 코드는 이게 끝.

  • 이렇게 구조를 잡아주면, styled-components 전용 파일을 만들어서 css를 시작하면 됨. 사실 이게 제일 손이 많이 감.

너무 간단하다고 생각했는데, 리액트 돔으로 감싸는게 생각보다 엄청 헷갈렸음. 그렇지만 구조 잡는건 얼마 안걸림. 딱 저 순서가 전부였음 물론 컴포넌트가 많아지고 서비스가 큰 웹인 경우 단순하지 않겠지만 나름 나쁘지 않았다 !

배포했눈데 볼래오? https://gazero-marvel.netlify.app/

  • 수정 수정 수정 상황
  • 폰트와 상세페이지 동영상 자동재생, 오토플레이, 작업을 추가로 진행함
profile
`나는 ${job} 개발자`

0개의 댓글