- ํ์ฌ ๋ฐฐํฌ๋ page์์๋ Mixed Content ์ด์๊ฐ ์์ต๋๋ค. ์ ๊ณตํด์ฃผ๋ api๊ฐ http์ด๊ธฐ์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ๋๋ค.
- fake data๋ฅผ ํ์ฉํ์ฌ ์ผ์์ ์ธ ํ์ด์ง ๋์์ ๊ฐ๋ฅํ๊ฒ ํ์์ต๋๋ค.
- ๋ก์ปฌ์์ ์์ํ๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
npm i
npm run dev
- ์ฅ๋ฐ๊ตฌ๋ ๊ธฐ๋ฅ์ด ์๋ ์ํํ์ด์ง๋ฅผ ๊ตฌํํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ธ ๋์์ธ์ ํด๋น ๋งํฌ์์ ํ์ธํ ์ ์์ต๋๋ค. ํด๋น ํ๋ก์ ํธ์ ๋ชฉ์ ์ ์ฃผ์ด์ง ๋์์ธ์ ๋ง์ถ์ด ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ๋ก ์ ํ์ตํฉ๋๋ค.
- ์์์ผ ๋ฐฉ๋ฒ๋ก ์ค ์คํฌ๋ผ ๋ฐฉ๋ฒ์ ํ์ฉํด์ ์งํํฉ๋๋ค. github์ ํ๋ก์ ํธ๋ฅผ ํ์ฉํ์ต๋๋ค. ๋งํฌ
- ๋์์ธ ๋งํฌ
- path: /
- Header์ Footer๋ฅผ ๊ฐ๊ณ ์์ผ๋ฉฐ, ํด๋น GNB์ Footer๋ ์ด๋ ํ์ด์ง๋ฅผ ๊ฐ๋๋ผ๋ ํญ์ ์กด์ฌํด์ผ ํ๋ค.
- Header ๋ด ํ๋ฒ๊ฑฐ ๋ฒํผ ์กด์ฌ, ํ๋ฒ๊ฑฐ ๋ฒํผ ํผ์น ์ ๋ด๋ถ์
- Header๋ ํ์ด์ง ๋ด ์คํฌ๋กค์ด ๋ฐ์ํ๋๋ผ๋ ํญ์ ์๋จ์ ๋ถ์ด์์ด์ผ ํ๋ค.
- ๋ฉ์ธ๋ก๊ณ โ ํด๋ฆญํ๋ฉด / ํ์ด์ง๋ก ์ด๋
- ํ๋ฒ๊ฑฐ ๋ฒํผ
- ์ํ๋ฆฌ์คํธ โ ํด๋ฆญํ๋ฉด /products/list ํ์ด์ง๋ก ์ด๋
- ๋ถ๋งํฌํ์ด์ง โ ํด๋ฆญํ๋ฉด /bookmark ํ์ด์ง๋ก ์ด๋
- Footer
- ์ผ๋ จ์ ํ ์คํธ ์ ๋ณด๋ค
- Header ๋ด ํ๋ฒ๊ฑฐ ๋ฒํผ ์กด์ฌ, ํ๋ฒ๊ฑฐ ๋ฒํผ ํผ์น ์ ๋ด๋ถ์
- ํด๋น ๋ฉ์ธํ์ด์ง์์๋
- ๋ชจ๋ ํ์
์ ์ํ ์ ๋ณด๋ฅผ 4๊ฐ ๋ณด์ฌ์ค๋ค (ํํฐ๊ธฐ๋ฅ ์์ด)
- ๋ณด์ฌ์ง๋ ์ํ์ ํ์ ์ ํผํฉ๋์ด ์์ ์ ์๋ค (์ํ, ์นดํ ๊ณ ๋ฆฌ, ๊ธฐํ์ , ๋ธ๋๋)
- ๋ชจ๋ ํ์
์ ๋ถ๋งํฌ ๋ ์ํ ์ ๋ณด๋ฅผ 4๊ฐ ๋ณด์ฌ์ค๋ค (ํํฐ๊ธฐ๋ฅ ์์ด)
- ๋ณด์ฌ์ง๋ ์ํ์ ํ์ ์ ํผํฉ๋์ด ์์ ์ ์๋ค (์ํ, ์นดํ ๊ณ ๋ฆฌ, ๊ธฐํ์ , ๋ธ๋๋)
- ๋ชจ๋ ํ์
์ ์ํ ์ ๋ณด๋ฅผ 4๊ฐ ๋ณด์ฌ์ค๋ค (ํํฐ๊ธฐ๋ฅ ์์ด)
- path: /products/list
- ์๋ฒ์์ ์ ๊ณตํ๋ ์ํ ๋ฆฌ์คํธ๋ค์ ํ์ธํ ์ ์๋ ํ์ด์ง์ด๋ฉฐ
- ๋ฌดํ ์คํฌ๋กค์ ํตํด ์ํ๋ค์ ๊ณ์ ๋ณด์ฌ์ค ์ ์์ด์ผ ํ๋ค .๋ฌดํ์คํฌ๋กค์ ์ฟผ๋ฆฌํ๋ผ๋ฏธํฐ๋ฅผ ํตํ ๋งค๋ฒ api call์ด ์๋, ์ต์ด 1๋ฒ api call์ ํตํด ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์จ ํ ์ ์ฉํฉ๋๋ค.
- ์ํ์ ๊ฐ ์ํ๋ณ๋ก ํ์ ์ด ์กด์ฌํ๋ค. (์ํ, ์นดํ ๊ณ ๋ฆฌ, ๊ธฐํ์ , ๋ธ๋๋)
- ์๋จ์ ํํฐ ๋ฒํผ์ ํตํด ์ํ์ ํ์ ๋ณ๋ก ์กฐํํด ๋ณด์ฌ์ค ์ ์์ด์ผ ํ๋ค.
- ๊ฐ ์ํ์ ํด๋ฆญํ๋ฉด ํด๋น ์ํ์ ์ฌ์ง์ ๋ณด์ฌ์ฃผ๋ ๋ชจ๋ฌ์ ๋์ธ ์ ์์ด์ผ ํ๋ค.
- ๊ฐ ์ํ์ ์กด์ฌํ๋ ๋ถ๋งํฌ ๋ฒํผ์ ๋๋ฌ ์ํ๋ ์ํ์ ๋ถ๋งํฌ ํ ์ ์์ด์ผ ํ๋ค.
- ์ด๋ฏธ ๋ถ๋งํฌ ๋ ์ํ์ ๊ฒฝ์ฐ, ๋ถ๋งํฌ ๋ฒํผ์ ํ์๋ฅผ ํด์ฃผ์ด์ผ ํ๋ฉฐ ๋ค์ ํ ๋ฒ ๋ถ๋งํฌ ๋ฒํผ์ ํด๋ฆญ ์ ํด๋น ์ํ์ ๋ถ๋งํฌ์์ ์ญ์ ํ๋ค.
- ๋ถ๋งํฌ ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ถ๋งํฌ์ ์ถ๊ฐ ํ ๋ ๊ทธ๋ฆฌ๊ณ ์ญ์ ํ ๋๋ ์ฌ์ฉ์์๊ฒ ์๋ฆผ ํ ์คํธ๊ฐ ํ์๋์ด์ผ ํ๋ค.
- path: /bookmark
- ์ฌ์ฉ์๊ฐ ๋ถ๋งํฌ ํ ์ํ ๋ค์ ํ์ธํ ์ ์๋ ํ์ด์ง๋ก ๋ฌดํ ์คํฌ๋กค์ด ๊ฐ๋ฅํด์ผ ํ๋ค.
- ์ํ๋ฆฌ์คํธ ํ์ด์ง์ ์กด์ฌํ๋ ํํฐ๋ง ๋ฒํผ๊ณผ ๊ฐ์ ๋ฒํผ์ ์ด์ฉํด ์ํ์ ํ์ ๋ณ๋ก ํํฐํด ๋ณด์ฌ์ค ์ ์์ด์ผ ํ๋ค.
๐ฆCH4
โ ๐fe-sprint-coz-shopping
โ โฃ ๐.git
โ โฃ ๐.husky
โ โฃ ๐ node_modules
โ โฃ ๐src
โ โ โฃ ๐api
โ โ โ โ ๐api.jsx // api๋ถ๋ฌ์ค๊ธฐ
โ โ โฃ ๐assest
โ โ โ โฃ ๐all.png
โ โ โ โฃ ๐brand.png
โ โ โ โฃ ๐category.png
โ โ โ โฃ ๐exhibition.png
โ โ โ โฃ ๐logo.png
โ โ โ โ ๐product.png
โ โ โฃ ๐components
โ โ โ โฃ ๐Bookmark.jsx
โ โ โ โฃ ๐Card.jsx
โ โ โ โฃ ๐CardList.jsx
โ โ โ โฃ ๐Description.jsx
โ โ โ โฃ ๐Dropdown.jsx
โ โ โ โฃ ๐Filter.jsx
โ โ โ โฃ ๐FilterList.jsx
โ โ โ โฃ ๐Footer.jsx
โ โ โ โฃ ๐Header.jsx
โ โ โ โฃ ๐Loading.jsx
โ โ โ โฃ ๐Modal.jsx
โ โ โ โฃ ๐PageTamplet.jsx // ๋ถ๋งํฌ ์ํํ์ด์ง ์ปดํฌ๋ํธ
โ โ โ โฃ ๐Toast.jsx
โ โ โ โฃ ๐ToastContainer.jsx
โ โ โ โ ๐Xmark.jsx
โ โ โฃ ๐hook
โ โ โ โฃ ๐useApi.jsx
โ โ โ โ ๐useClick.jsx //ํค๋์ ํ๋ฒ๊ฑฐ ์์ด์ฝ click hook
โ โ โฃ ๐pages
โ โ โ โฃ ๐Bookmark.jsx
โ โ โ โฃ ๐Home.jsx
โ โ โ โฃ ๐NotFound.jsx
โ โ โ โ ๐ProductLists.jsx
โ โ โฃ ๐redux //redux reducer, store,action๋ค์ ์ ๋ฆฌ
โ โ โ โฃ ๐action
โ โ โ โ โ ๐actions.js
โ โ โ โ ๐reducer
โ โ โ โ โฃ ๐hambegeReducer.js //ํค๋์ ํ๋ฒ๊ฑฐ ์์ด์ฝ ๊ด๋ จ reducer
โ โ โ โ โฃ ๐modalReducer.js //๋ชจ๋ฌ ๊ด๋ จ reducer
โ โ โ โ โฃ ๐reducer.js // bookmark๊ด๋ จ reducer
โ โ โ โ โฃ ๐rootReducer.js // Root reducer
โ โ โ โ โฃ ๐store.js
โ โ โ โ โ ๐toastReducer.js // Toast UI๊ด๋ จ reducer
โ โ โฃ ๐routers
โ โ โ โ ๐Routers.jsx
โ โ โฃ ๐util
โ โ โ โ ๐getRandomForSlice.js
โ โ โฃ ๐App.jsx
โ โ โฃ ๐GlobalStyle.jsx
โ โ โฃ ๐main.jsx
โ โ โ ๐theme.js
โ โฃ ๐.eslintrc.cjs
โ โฃ ๐.gitignore
โ โฃ ๐.prettierrc
โ โฃ ๐index.html
โ โฃ ๐package-lock.json
โ โฃ ๐package.json
โ โฃ ๐README.md
โ โ ๐vite.config.js
Vite.+.React.6.mp4
- ๊ธฐ์กด CRA๋ก ํ์ฑํ react ํ ํ๋ฆฟ์์๋ BrowserRouter๋ก ๊ฐ์ธ๋ ํํ๋ก ์์ ํ์์ ๋ ์ ์์ ์ผ๋ก ์ถ๋ ฅ์ด ๋์์ง๋ง, vite ํ ํ๋ฆฟ์์๋ ์๋์ด ๋์ง ์์์ ๊ณต์ ํํ์ด์ง ๋ํ ๋ฆฌ์ผ์ ์ฐธ๊ณ ํ๋ฉด์ ๋ค์ ์งํํ์์ต๋๋ค.
- ๊ณต์ ๋ธ๋ก๊ทธ
- 4๊ฐ์ ํ์ด์ง๋ฅผ ๋ง๋ค์ด์ ๊ธฐ๋ณธ router ๊ตฌ์ฑ Home, ProductList, Bookmark, NotFound
- BrowserRouter์ createBrowserRouter์ ์ฐจ์ด์ ๋ํด์ ์ดํดํ ์ ์์๋ค. createBrowserRouter์์๋ DataRoiter๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์๋ค. (ex. data APIs) ๋ฐ๋ผ์ NotFound ํ์ด์ง์์ ์ฌ์ฉํ๊ณ ์๋ useRouteError ํ ์ createBrowserRouter์์๋ง ์ฌ์ฉ๊ฐ๋ฅํ์๋ค. ๋งํฌ
- App์ ์ ๋๊ฒฝ๋ก๋ก ์ค์ ํ์ฌ Router ์์ ์ ์งํํ์์ต๋๋ค. ์ด๊ธฐ์ createBrowserRouter์์ ์ ๊ณตํ๋ DataAPIs๊ฐ ๋งค์ฐ ๋งค๋ ฅ์ ์ผ๋ก ๋ค๊ฐ์์ต๋๋ค. ํนํ DataAPIs๊ฐ ์ ๊ณตํ๋ ์ฌ๋ฌ ํ ์ค์์ useRouteError๊ฐ ๋งค๋ ฅ์ ์ด์์ต๋๋ค. ์ค์ ์ ๋ฐ๋ผ์ router ์ ๋ฌ ๋ฟ๋ง ์๋๋ผ, ๋ค๋ฅธ ์ ๋ฌ๋ ์บก์ณํด์ ํ์ด์ง๋ฅผ ์๋์ผ๋ก ์ ํ ํด์ฃผ๋ ๊ธฐ๋ฅ์ด ์ธ์๊น์์ต๋๋ค. ์ด๋ฌํ APU๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ createBrowserRouter๋ฅผ ์ ์ฉํ์์ต๋๋ค.
- ์ฌ๊ธฐ์ ๋ฌธ์ ๋ createBrowserRouter๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ Outlet๊ณผ ํจ๊ป ์ฌ์ฉ๋๋๋ฐ, ์ ๋ ๊ฐ๊ฐ์ ํ์ด์ง์ prop์ ๋ฌ์ ํ๊ณ ์ถ์ด์ Routes์ Route๋ฅผ ํ์ฉํ์ต๋๋ค.
// ./routers/Routers.jsx
import { createBrowserRouter } from "react-router-dom";
import NotFound from "../pages/NotFound";
import ProductLists from "../pages/ProductLists";
import Bookmark from "../pages/Bookmark";
import App from "../App";
import Home from "../pages/Home";
const router = createBrowserRouter([
{
path: "/",
element: <App />,
children: [
{
path: "/",
element: <Home />,
},
{
path: "/products/list",
element: <ProductLists />,
},
{
path: "/bookmark",
element: <Bookmark />,
},
],
errorElement: <NotFound />,
},
]);
export default router;// ./App.jsx
import { Routes, Route } from "react-router-dom";
import Header from "./components/Header";
import Footer from "./components/Footer";
import Home from "./pages/Home";
import ProductLists from "./pages/ProductLists";
import Bookmark from "./pages/Bookmark";
import useHeaderClick from "./hook/useHeaderClick";
import NotFound from "./pages/NotFound";
import useApi from "./hook/useApi";
import { useDispatch } from "react-redux";
import { dispatchData } from "./redux/action/actions";
import { useEffect, useState } from "react";
import Toast from "./components/Toast";
function App() {
// header ํด๋ฆญ ์ ์ฉํ๊ธฐ
const { click, setClick, handleClick } = useHeaderClick();
//api ๋ถ๋ฌ์ค๊ธฐ
const { data, isLoading } = useApi();
//Toast ์กฐ์
const [toast, setToast] = useState(false);
const [toastBookmar, setToastBookmark] = useState(false);
useEffect(() => {
const id = setTimeout(() => {
setToast(false);
}, 1000);
return () => {
clearTimeout(id);
};
}, [toast, toastBookmar]);
//query ๋ฐ์ดํฐ redux์ ์ ์ฅํ๊ธฐ
const dispatch = useDispatch();
useEffect(() => {
dispatch(dispatchData(data));
}, []);
return (
<>
<Header click={click} setClick={setClick} handleClick={handleClick} />
<Routes>
<Route
path="*"
element={
<Home
handleClick={handleClick}
isLoading={isLoading}
setToast={setToast}
setToastBookmark={setToastBookmark}
/>
}
/>
<Route
path="/products/list"
element={
<ProductLists
handleClick={handleClick}
setToast={setToast}
setToastBookmark={setToastBookmark}
/>
}
/>
<Route
path="/bookmark"
element={
<Bookmark
handleClick={handleClick}
setToast={setToast}
setToastBookmark={setToastBookmark}
/>
}
/>
<Route path="/*" element={<NotFound />} />
</Routes>
{toast && <Toast toastBookmar={toastBookmar} />}
<Footer handleClick={handleClick} />
</>
);
}
export default App;๐ฃ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ์์ ๋, ์ฝ์์์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๊ณ ์ฐฝ์ ๋ณด์ฌ์ง๊ฒ ๋ฉ๋๋ค.
history.ts:487 You rendered descendant <Routes> (or called `useRoutes()`) at "/" (under <Route path="/">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
Please change the parent <Route path="/"> to <Route path="*">.
- ์ ์ํ ํด๊ฒฐ๋ฐฉ๋ฒ ์ฒ๋ผ path๋ฅผ ์์ ํ ์ํ์์๋ ์ด์ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ณ ์์ต๋๋ค. createBrowserRouter์ Routes๋ฅผ ํผํฉํด์ ์ฌ์ฉํ ๋ฌธ์ ์ธ๋ฏ ํ์ฌ, ํ๋์ ๋ฐฉ์๋ง ์ฌ์ฉํ๋๋ก ์์ ์ด ํ์ํ ๊ฒ ๊ฐ์ต๋๋ค.
- styledComponent์ ์ ์ญ ์คํ์ผ ์ค์ ํ๊ธฐ,
createGlobalStyle๋ฅผ ํ์ฉํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ reset css๋ฅผ ์ ์ฉํ์ต๋๋ค. reset css - styledComponent Theme์ ํ์ฉํด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ ํฐํธ์ ํฌ๊ธฐ, ๊ฐ margin ๊ฐ, color๋ฅผ ์ค์ ํ์ต๋๋ค.
- reset css๋ก ์ธํด ๋ณํ๋ NotFound Page์ css๋ฅผ ์์ ํ์ต๋๋ค.
- ํค๋ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ์ต๋๋ค. ์ต๋ํ ํผ๊ทธ๋ง์์ ์์ฑํ ๋์์ธ๊ณผ ์ ์ฌํ๊ฒ ๋ง๋ค๋๋ก ๋ ธ๋ ฅํ์ต๋๋ค.
- icon ๊ฐ์ ๊ฒฝ์ฐ svg ์ fontawsome ์์ด์ฝ์ ํจ๊ป ํ์ฉํด์ icon์ ํ์ฉํ์ต๋๋ค.
- ๋งํ์ ๊ฐ์ ๊ฒฝ์ฐ๋ ๋ค์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ์ต๋๋ค. ๋งํฌ
- ํค๋ ์ปดํฌ๋ํธ์ ํ๋ฒ๊ฑฐ๋ฅผ ํด๋ฆญํ๋ฉด Dropdown ํํ๋ก ๋ฉ๋ด๊ฐ ๋ฑ์ฅํด์ผ ํฉ๋๋ค. ์ด๋ ํ๋ฒ๊ฑฐ ๋ฒํผ์ด ํด๋ฆญ ๋์ด์ผ ํ๋ฒ๊ฑฐ๊ฐ ์ฌ๋ผ์ง๊ฒ ๋๋ ํํ๊ฐ ๋ถํธํ๋ค๊ณ ๋๊ผ์ต๋๋ค. ๊ทธ๋์ ์ ์ญ์์ state๋ฅผ ๊ฐ์งํด์ ์ฌ์ฉํ ์ ์๋๋ก ์์ ํ์ต๋๋ค. component hook useHeaderClick์ ๋ง๋ค์ด์ App ์์์ state๋ฅผ ๊ด๋ฆฌํ๋๋ก ํ์์ต๋๋ค. ํ๋ฒ๊ฑฐ ๋ฒํผ์ด ํด๋ฆญ ๋์ด DropDown ์ปดํฌ๋ํธ๊ฐ ๋ณด์ด๋ ์ํ๋ผ๋ฉด, ์ด๋ค ํ๋ฉด์ ํด๋ฆญํด๋ ๋ค์ ๋ซํ๋๋ก ๊ตฌ์ฑํ์ต๋๋ค.
- FooterComponent ๊ตฌํ.
- react-query๋ฅผ ํ์ฉํด์ API ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์์ต๋๋ค.
- ์ด๊ธฐ์๋ api ํจ์๋ง์ ๋ฐ๋ก ๋ถ๋ฆฌํ์๋๋ฐ, ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ hook ๋ํ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข์ ๋ฏ ํ์ฌ useApi component hook์ ๋ง๋ค์์ต๋๋ค.
-
Card Component๋ฅผ ๋ง๋ค์์ต๋๋ค. API์ ํ์ ์์ฑ์ ๋ฐ๋ผ ์ค๋ช ๋ชจ์์ ์ฐจ์ด๊ฐ ์์ด์ Description.jsx ์ปดํฌ๋ํธ์์ ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ์ฌ ๋ ๋๋งํ๋๋ก ์์ฑํ์ต๋๋ค.
-
๊ฐ๊ฒฉ๊ณผ follower ๊ฐ์ ๊ฒฝ์ฐ๋ ์ผํ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ ๊ทํํ์์ ํ์ฉํ์ต๋๋ค.
toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
- ๋ชจ๋ฌ ๋ง๋ค๊ธฐ๋ ์์ ์ ๋ง๋ Modal component๋ฅผ ์ฐธ๊ณ ํ์ต๋๋ค. Modal Link
-
์ฐ์ rtk query๋ฅผ ์ฌ์ฉํ์ง ์๊ณ , react query๋ฅผ ํ์ฉํ๊ณ ์ ํ๋ค. ๋ฐ๋ผ์ react query๋ก ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ redux์ ๋ฐ์ดํฐ๋ก ๊ตฌ์ฑํ๋ action์ ๋ง๋ค์ด์ผ ํ๋ค. ๋๋ถ์ด data๋ฅผ ๋ฐ์ ์ฌ ๋, ๋ฐ์ดํฐ ๋ด์์ bookmark์ ๊ดํ ์ ๋ณด๊ฐ ์๊ธฐ ๋๋ฌธ์, bookmark ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ค.
-
๋จผ์ redux-toolkit์ ํ์ฉํด์ ์ฝ๋๋ฅผ ์์ฑํ์๋ค. ์ด 3๊ฐ์ action์ ์ํํ๋๋ก ์์ฑํ์๋ค. bookmark ์ถ๊ฐ ๊ธฐ๋ฅ๊ณผ bookmark ํด์ ๊ธฐ๋ฅ, react-query์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐ ๋ฐ์ดํฐ๋ก ์ค์ ํ๋ ๊ฒ์ด๋ค.
-
์ด๋ ์ด๋์ react query๋ก ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํด์ redux๋ก ๋ณด๋ด์ฃผ๋๊ฐ๊ฐ ๋ฌธ์ ์๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๊ฐ์ฅ ์ต์์์ธ App์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ณ ์ด๋ฅผ dispatchํ๋๋ก ๊ตฌ์ํ์๋ค.
- bookmark ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ , useEffect๋ฅผ ํ์ฉํด์ App.jsx์์ ์ต์ด๋ก API ๋ฐ์ดํฐ๋ฅผ redux๋ก ๋ณด๋ด๋๋ก ์ค์ ํ์๋ค. ์ด๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋, ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจ ํ์์๋, react query์์ cashe๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๊ธฐ์ ์๋กญ๊ฒ ๋ณด๋ด๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค. ๋ํ ๋งค๋ฒ ์๋ก ๊ณ ์นจ ํ ๋๋ง๋ค ๋ฐ์ดํฐ๊ฐ ์ด๊ธฐํ ๋๊ธฐ ๋๋ฌธ์ ๋ถ๋งํฌ ๊ธฐ๋ฅ์ด ์์ฉ์ด ์์๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด localstorage๋ฅผ ํ์ฉํ๋ค.
6.3 redux-persist ์ ์ฉํ๊ธฐ ์ฐธ๊ณ
-
redux ๊ณผ๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์์ local storage๋ฅผ ์ ์ฉํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ์ฝ๋๋ฅผ ์์ฑํ๋ค. ์ด๋ redux-toolkit์ผ๋ก ์์ฑํ ์ฝ๋๋ฅผ ์ ์ฉํ๋ ๊ณผ์ ์์ ์ ๋ฌ๊ฐ ์ง์์ ์ผ๋ก ๋ฐ์ํด, toolkit์ ํ์ฉํ์ง ์๊ณ ์ผ๋ฐ redux์ react-redux๋ฅผ ํ์ฉํ๋ ์ฝ๋๋ก ์์ ํ์๋ค.(์์ง toolkit์ ์ต์ํ์ง ์์ ์ด๋์ ๋ฐ์ํ๋ ์ค๋ฅ์ธ์ง ์ฐพ์ ์ ์์ด ์ฝ๋๋ฅผ ์ ์ฒด์ ์ผ๋ก ์์ ํ๋ค.!) ์ถ๊ฐ์ ์ผ๋ก localStorage์ ์ ์ฅ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, react-query ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ์ง ์๊ณ , localStorage ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋๋ก initialvalue๋ฅผ ์์ ํ์๋ค.
-
์ ์ ์๋์ ํ ์คํธ ํด๋ณด๋ ์๋์ ์ ์์ ์ผ๋ก ํ์๋ค. ๋ค๋ง localStorage๋ฅผ ์ ์ฉํ๋ ๋ฉ์ธ ํ์ด์ง์ ์ํํ์ด์ง๊ฐ ๊ณ ์ ๋ ์ํ๋ง ๋ณด์ฌ์ฃผ๊ฒ ๋์ด ์ด๋ฅผ ์์ ํ๊ธฐ ์ํด random์ผ๋ก ์ซ์๋ฅผ ๋ฝ๋ ํจ์๋ฅผ ์์ฑํ๋ค.
-
redux์์ actions์ ๋ฐ๊ณ reducer์ ํ๋ ๊ณผ์ ์์ store์ ์ ์ฅ๋ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์ด ํน์ ๊ณผ์ ์์ ์ ๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ํ์ธํ์ต๋๋ค. ์ด๋ฅผ ์์ ํ๊ธฐ ์ํด์ redux-persist๊ฐ ์ ์ฅํ๋ ๋ฐ์ดํฐ ํํ๋ก state์ ๋ฐ์ดํฐ ํํ๋ฅผ ์์ ํ์์ผ๋ฉฐ, ๊ฐ๊ฐ์ action์ด ๋ฐํํ๋ ๋ฐ์ดํฐ์ ํํ๋ ์ผ์น์์ผฐ์ต๋๋ค.
- filter ๋ฒํผ์ ๊ณ ์ ๋ ํํ์ ๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ณํ๋ ์ผ์ด ์๊ธฐ ๋๋ฌธ์, index๋ก key ๊ฐ์ ์ฃผ์ด๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
- ๊ฐ๊ฐ์ ๋ฒํผ์ ์ฌ์ฉํ ์ด๋ฏธ์ง๋ฅผ ๋ฐฐ์ด ํํ๋ก ๊ฐ์ง๊ณ ์ค๊ณ , ๊ฐ ๋ฒํผ์ ์ด๋ฆ๋ํ ๋ฐฐ์ด๋ก ์ ๋ฆฌํ์ต๋๋ค.
- ๋ฒํผ์ด ํด๋ฆญ ๋์์ ๋, ๋ฒํผ์ ๊ฐ์กฐํ๊ธฐ ์ํ css ์์ ์ด ํ์ํ์ต๋๋ค. ์ด๋ฅผ ์ํด numState๋ฅผ useState๋ฅผ ํตํด state๋ก ๋ง๋ค์์ต๋๋ค. ๋ฒํผ์ด ํด๋ฆญ๋์์ ๋, ๊ฐ ๋ฒํผ์ index์ ๋ง์ถ์ด numState์ ๊ฐ์ index์ ๊ฐ์ผ๋ก ์์ ํ์ต๋๋ค. ์ด๋ฅผ ํตํด์ index์ numState์ ๊ฐ์ด ๊ฐ์๋, ํด๋น ๋ฒํผ์ด ํด๋ฆญ ๋์๋ค๋ ํ์๋ฅผ ํ ์ ์๋๋ก ์์ฑํ์์ต๋๋ค.
- ๋ ํ์ด์ง์ ํํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฐฉ์๋ง ๋ค๋ฅผ ๋ฟ ๋ชจ๋ ๋๊ฐ์ด ์์ฑํ์ต๋๋ค. ๋ค๋ง ๊ฐ์ ์ฝ๋๊ฐ ๋๋ฌด ๋๊ฐ์ด ๋ฐ๋ณต๋์ด ๋ชจ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ์ ์ฝ๋ ๋ฆฌํํ ๋ง์ ํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.
- ๋ํ numState์ ์ํ์ ๋ฐ๋ผ ํ๋ฉด์ ๋ฟ๋ ค์ค ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ธ์ต๋๋ค. ์ด ๊ณผ์ ์์๋ ๊ฐ์ ์ฝ๋๋ฅผ 5๋ฒ์ด๋ ๋ฐ๋ณตํด์ ์ญ์ ์ดํ์ ๋ฆฌํํ ๋ง์ด ํ์ํ ๊ฒ ๊ฐ์ต๋๋ค.
- ์ฒ์ ์๊ฐํ ๋ฐฉ์์ redux๋ฅผ ํตํ toastUI ๊ตฌ์ฑ์ด์์ต๋๋ค. ๋ง์นจ CH3 redux๋ฅผ ํ์ตํ ๋น์์ ์์ ์ฝ๋์ redux middleware ์ค ํ๋์ธ thunk๋ฅผ ํ์ฉํ์ฌ toast ui์์ ์ ํ ์ฝ๋๊ฐ ์์ด์ ์ด๋ฅผ ๋ฆฌํํ ๋ง ํ์ฌ ์์ ์ ํ๋ฉด ๋ ๊ฒ ๊ฐ์์ต๋๋ค.
- ํ์ง๋ง redux๋ฅผ ํ์ฉํ๊ธฐ ์ํด์ ํฌ๊ฒ ๋ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ก ํ๋์ ๊ธฐ๋ฅ ๊ตฌํ์ ์ํด์ ์๋ก์ด reducer๋ฅผ ์์ฑํ๊ณ ์ ์ญ ๋ณ์๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๋๊ฒ ๊ณผ์ฐ ๋ง์๊น? ๋ผ๋ ์๋ฌธ์ ๊ฐ์ง๊ฒ ๋์์ต๋๋ค. ํ๋์ ๊ธฐ๋ฅ์ ์ํด ๊ตฌํํ ๋ถ๊ฐ์ ์ธ ์ฝ๋๊ฐ ๋๋ฌด๋ ๋ง์์ง๋ค๊ณ ์๊ฐํ์์ต๋๋ค. ๋ํ ํ์ฌ ๊ตฌํํ๋ APP์ ๊ท๋ชจ๊ฐ ๊ทธ๋ฆฌ ํฌ์ง ์๊ธฐ ๋๋ฌธ์ ๊ตณ์ด toast๋ฅผ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํด์ผ ํ ํ์๋ฅผ ๋๋ผ์ง ๋ชปํ์ต๋๋ค.
- ๊ทธ๋์ useState์ useEffect๋ฅผ ํ์ฉํ์ฌ Toast UI๋ฅผ ์์ ํ๋๋ก ํ์์ต๋๋ค.
- ์ฒ์์๋ Bookmark ์ปดํฌ๋ํธ์ Toast ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ์ฌ ์์ ์ ํ๋ ค ํ์ต๋๋ค. ํ์ง๋ง ์ด๋ ๊ฐ Card ์ปดํฌ๋ํธ ๋ณ๋ก Toast ์ปดํฌ๋ํธ์ ์์น๊ฐ ์กํ์ง๊ณ ์ต๋ 100๊ฐ์ Toast ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค. ์ด๋ ๊ณ ์ ๋ ํ๋์ position์ ์ก๋ ๊ฒ์ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ๊ทธ๋์ Toast ์ปดํฌ๋ํธ์ ์์น๋ฅผ APP์ ์์นํ์ฌ ํ๋์ ์ปดํฌ๋ํธ ๋ง์ state ์ฒ๋ฆฌ๋ฅผ ํตํด ๋ถ๋ฌ์ค๋๋ก ํ์์ต๋๋ค.
- ์ด ๋๊ฐ์ state๋ฅผ ํ์ฉํ์์ต๋๋ค. toastBookmark์ toast state๋ฅผ ํ์ฉํ์์ต๋๋ค. toastBookmar๋ ๋ณด์ฌ์ฃผ์ด์ผ ํ Toast์ ํํ๋ฅผ ๊ฒฐ์ ํ๋ state์ด๊ณ toast state๋ toast๋ฅผ ํ๋ฉด์ ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ๋ state๋ก ์๋ํ๋๋ก ๊ตฌ์ฑํ์์ต๋๋ค.
- ์ดํ useEffect๋ฅผ ํตํด setTimeout์ ์ค์ ํด์ ์์ ์ ํ์์ต๋๋ค. ์์กด์ฑ ๋ฐฐ์ด์ toastBookmark์ toast๋ฅผ ์ถ๊ฐํ์ฌ ํด๋น ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ ๋ง๋ค useState๊ฐ ์คํ๋๋๋ก ์์ฑํ์์ต๋๋ค.
- "react-intersection-observer"๋ฅผ ํตํด ๊ตฌํํ์์ต๋๋ค.
- ํ๋ฉด ๊ฐ์ ์ด๋์ค, ๋ถ๋ฌ์จ ๋ฌดํ ์คํฌ๋กค์ด ์ ์ง ๋์ง ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.
- ์ฒ์์ผ๋ก createBrowserRouter๋ฅผ ํ๋ก์ ํธ์ ์๋ํด ๋ณด์์ ๋, ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๊ณ ๊ฐ ์ฝ์์ ๋ํ๋ฌ์ต๋๋ค.
history.ts:487 You rendered descendant <Routes> (or called `useRoutes()`) at "/" (under <Route path="/">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
Please change the parent <Route path="/"> to <Route path="*">.
-
์ด๋ Routes๋ฅผ ์ค์ฒฉ์ผ๋ก ์ฌ์ฉํ์ฌ ์๊ธด ์ํ ๊ฒฝ๊ณ ์์ต๋๋ค. ๊ทธ๋์ createBrowserRouter, BrowserRouter์ค ํ๋๋ฅผ ์ ํํด์ ์ ์ฉ์ ํด์ผ ํ์ต๋๋ค.
-
์ด๋ฅผ ์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก Outlet์ ํ์ฉํ๋ ๊ฒ์ด์์ต๋๋ค. ํ์ง๋ง ์ ์ ์ฝ๋์์ ์ ์ญ์์ ๊ด๋ฆฌํด์ผ ํ state๋ฅผ ๋ฟ๋ ค ์ฃผ๊ณ ์๋ ์ํฉ์์ Outlet์์ Prop ์ ๋ฌ์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์์ต๋๋ค. ๋ฐ๋ผ์ contextAPIํน์ reducer๋ฅผ ํ์ฉํด์ ์ด๋ฅผ ๊ด๋ฆฌํ๊ณ ์ ํฉ๋๋ค.
-
๋ฌผ๋ก useRoutes๋ loader์ ๊ฐ์ ์๋ก์ด ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด ๋์ง๋ง, ์ ํ๋ ์๊ฐ ๋ด์ ์ด๋ฅผ ๋ค์ ํ์ตํ๋ ๊ฒ์ ์ด๋ ค์์ด ์์์ต๋๋ค. ๊ทธ๋์ ์ด๋ฅผ ์๋ก์ด reducer๋ฅผ ๋ง๋ค์ด์ ๊ด๋ฆฌํ๊ณ ์ ํฉ๋๋ค. ์ถํ createBrowerRouter๋ฅผ ํ์ตํ๊ณ ์ ํฉ๋๋ค.
- Theme์ ํํ๋ฅผ ๋ณ๊ฒฝํ์ต๋๋ค.
- GlobalStyle์ #root์ base font-size๋ฅผ ์ง์ ํ ํ ๋ชจ๋ ์๋ ์์น์ธ rem์ผ๋ก ๋ณ๊ฒฝํ์ต๋๋ค.
- margin ๊ด๋ฆฌ๋ฅผ spacing06, spacing11๋ก ๋ณ๊ฒฝํ์ต๋๋ค. ์ด๋ ํด๋น ์ฌ์ดํธ๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ณ๊ฒฝํ์ต๋๋ค. ๋งํฌ
- ์ฒ์์ ์์ ๋ฐฉํฅ์ random์ผ๋ก ๋ฝ์ ์ซ์๊ฐ ๋ฐฐ์ด ๋ฐ์ดํฐ์ ๊ธธ์ด - 4๋ณด๋ค ํด์ ์ฃผ์ด์ง ๋ฐฐ์ด์์
[99,0,1,2]์์ผ๋ก ๋ฝ์๋ผ ๋ฐฉ์์ผ๋ก ์์ ํ๋ ค ํ๋ค. ๊ตฌํํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
export default getRandomForSlice(data){
const random = Math.floor(Math.random() * 100);
const { length } = data;
const sliceData = [];
for (let i = random; i < random + 4; i++) {
if (i > length - 1) {
sliceData.push({...data[i - length]});
} else {
sliceData.push({...data[i]});
}
}
return sliceData;
}- ์ด๋ ๊ฒ ํด์ ์๋ก์ด ๋ฐฐ์ด์ ๋ง๋ค๊ณ ์ด๋ฅผ state๋ก ๊ด๋ฆฌ ํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋ค. bookmark๊ฐ ๋ ์ ๋ณ ๋งํฌ์ ์์ด ๋ณํํด์ผ ํ๋๋ฐ, ๊ธฐ์กด์ stateํํ๋ฅผ ๊ณ ์ ์ผ๋ก ๊ฐ์ง๊ณ ์๊ธฐ์ redux์ ์ฐ๋๋ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค์ง ๋ชปํ๊ณ setState๋ฅผ ์์ ์ปดํฌ๋ํธ์๊ฒ ๋๊ฒจ ์์ ํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ ๋ถํ์ํ ์์ ์ด๋ผ๊ณ ๋๊ปด์ ๊ธฐ์กด์ ๋ฐฉ์์ฒ๋ผ number ๋ฐ์ดํฐ๋ฅผ ๋๊ฒจ์ฃผ๋ ํ์์ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ์ฑํํ์๋ค.
- ๋ง์ฝ ์ด๋ ๊ฒ ๋ฝ์์จ ๋ฐฐ์ด์ state๋ก ๊ด๋ฆฌํ์ง ์์์ ๋ถ๋งํฌ ํด๋ฆญ์ ๋ชจ๋ ์ํ ๋ฆฌ์คํธ๊ฐ ์ฌ๋ ๋๋ง ๋๊ธฐ ๋๋ฌธ์, ์ฌ์ฉ ์ธก๋ฉด์์ ๋ถํธํจ์ ๊ฒฝํํ๋ค.
- ๊ทธ๋์ ๊ธฐ์กด์ RandomNum์ ๋ฝ์์ฃผ๋ ํ์์ ์ฌ์ฉํ์๊ณ ์ฝ๋๋ฅผ ์ต์ข ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์๋ค.
export default function getRandomForSlice(data, chooseNum) {
return Math.floor(Math.random() * data.length - chooseNum);
}- ๋ฟ๋ ค์ค ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ๋ณ๊ฒฝ, ํน์ ์ ์ฒด ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ๋ณ๊ฒฝ๋ ๊ฒ์ ๊ณ ๋ คํ์ต๋๋ค.
- ๋ ๋๋ง ํ ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ๋ณํํ ๊ฒฝ์ฐ Home์์ ์์๋ก ๊ด๋ฆฌํ๊ณ ์๋ ๋ณ์๋ง ์กฐ์ ํ ๊ฒฝ์ฐ ์๋์ผ๋ก ๋ ๋๋ง ๋๋๋ก ์์ ํ์ต๋๋ค.
- ์ด์ ์๋ APP์ state๋ฅผ ์ค์ ํด์ ๊ฐ ํ์ด์ง์ ๋ฟ๋ ค์ฃผ๋ ํ์์ผ๋ก ์งํํ์ต๋๋ค. ํ์ง๋ง router๋ฅผ ์์ ํ๋ ๊ณผ์ ์์ ๊ฐ ๊ธฐ๋ฅ์ ๋ถ๋ฆฌํ๋ ๊ฒ ์ข์ ๊ฒ ๊ฐ์ ์ด๋ฅผ ์ ์ญ ๊ด๋ฆฌ ๋ณ์๋ก ๋ณ๊ฒฝํ์ต๋๋ค.
- hambegerReducer๋ฅผ ๋ง๋ค์ด ๊ด๋ฆฌ๋ฅผ ํ์์ผ๋ฉฐ, ๊ฐ ํ์ด์ง์์ Dropdown ์ปดํฌ๋ํธ๊ฐ ์ด๋ ค ์์์ ํ๋ฉด ์ด๋๋ฅผ ํด๋ฆญํด๋ ๋ซํ๋๋ก ํ๊ธฐ ์ํด์ ๋ณ๊ฐ์ ํ useClick์ ๋ง๋ค์ด์ ์ฝ๋๋ฅผ ์์ ํ์ต๋๋ค.
- ์ต์์ ์ปดํฌ๋ํธ์ธ APP์์ ์ ์ญ์ผ๋ก toast๊ด๋ จ state๋ฅผ ์ค์ ํ์ฌ ๊ฐ๊ฐ์ ํ์ด์ง์ ์นด๋ ์ปดํฌ๋ํธ์ ๋ฟ๋ ค์ฃผ๋ ๋ฐฉ์์ผ๋ก tost UI๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ด๋ ๋ง์ฃผ์น ๋ฌธ์ ๋ ์ด ๋ ๊ฐ์ง ์์ต๋๋ค.
- state ๊ด๋ฆฌ๊ฐ ์ด๋ ค์ ์ต๋๋ค. ๊ทธ๋ ๊ฒ ๊น์ ๊ตฌ์กฐ๋ ์๋์ง๋ง, state๊ฐ ์๋ชป ๋์์ ์ ์์ ํ๋ ๋ฐฉ๋ฒ์ด ์ฝ์ง ์์์ต๋๋ค.
- ํ๋์ toast ui๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ถฉ๋ถํ์ง๋ง, ๋ฐฐ์ด ํ์์ผ๋ก state๋ฅผ ๊ด๋ฆฌํ๊ณ ์ ํ ๋ ํ๋ ์ฝ๋ฉ์ด ๋๊ณ ํ๋์ state์ ๋๋ฌด ๋ง์ ๊ฐ์ ๊ด๋ฆฌํ๊ฒ ๋์์ต๋๋ค.
Vite.+.React.1.mp4
- useReducer๋ฅผ ํ์ฉํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ณต์กํด์ง๋ ๊ตฌ์กฐ๋ ํด๊ฒฐํ ์ ์์ง๋ง, ์ฌ์ ํ state ๊ด๋ฆฌ๊ฐ ์ด๋ ต๋ค๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ๋ฐ๋ผ์ contextAPI์ ํจ๊ป ์ฌ์ฉ์ ํด์ผ ํ์ต๋๋ค. ํ์ง๋ง ํ์ฌ ์ ์ญ ์ํ๊ด๋ฆฌ๋ก redux๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ redux๋ฅผ ํ์ฉํ๊ธฐ๋ก ํ์์ต๋๋ค.
- ๋น๋๊ธฐ๋ก ๋์ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ด๋ จ middleware์ธ redux-thunk๋ฅผ ์ค์นํ์ฌ ์๋ก์ด reducer๋ฅผ ๋ง๋ค์์ต๋๋ค. (toastReducer)
- toastReducer๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋น์๋ ์ํ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ์ต๋๋ค. ๋น ๋ฐฐ์ด์ ์ด๊ธฐ ๋ฐ์ดํฐ๋ก ์ค์ ํ์ฌ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ค๋ฉด ํ๋์ฉ ์์ด๊ณ ์ฒ์ ๋ค์ด์จ ๋ฐ์ดํฐ ๋ถํฐ ์ ๊ฑฐ๋๋ queue๋ฅผ ์ฐจ์ฉํด์ reducer์ ๊ตฌ์กฐ๋ฅผ ์์ฑํ์ต๋๋ค.
Vite.+.React.4.mp4
- ๊ธฐ์กด์๋ Modal์ Card ์ปดํฌ๋ํธ ์์ ์์นํ๊ฒ ํ์์ต๋๋ค. ์ด๋ ์ ์์ ์ผ๋ก ์๋ํ์ง๋ง, ๋ถ๋งํฌ ํ์ด์ง์์ ๋ถ๋งํฌ๋ฅผ ํด์ ํ ์ Card component๊ฐ unmount๋๋ฉด์ Modal ๋ํ ๊ฐ์ ๋ก ์ข ๋ฃ๋๋ ํ์์ด ์์์ต๋๋ค. (์์ ์์์์ ํ์ธํ ์ ์์ต๋๋ค.)
- ๋ฐ๋ผ์ Modal ์ปดํฌ๋ํธ๋ฅผ ์ ์ญ์์ ์ค์ ํด์ redux๋ฅผ ํตํด ์ํ ๊ด๋ฆฌ๋ฅผ ํ๋๋ก ์์ ํ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ฒ๊ทธ๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค.
Vite.+.React.5.mp4
// ./pages/home.js
<section>
<Title>์ํ ๋ฆฌ์คํธ</Title>
<List>
{state
.slice(randomNumber, randomNumber + CHOOSENUMBER)
.map((item) => (
<li key={item.id}>
<Card data={item} />
</li>
))}
</List>
</section>- ์์ ์ฝ๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด Component๋ก ๋ถ๋ฆฌํ์ฌ ์์ ํ์์ต๋๋ค.
<CardList
title={"์ํ ๋ฆฌ์คํธ"}
state={state.slice(randomNumber, randomNumber + CHOOSENUMBER)}
/>- ์ด์ ์๋ ์ง์ ํ๋ ํ์ดํ ํ๋ ์์ผ๋ก ๋ฌธ์์ด์ ์ฌ์ฉํ์ต๋๋ค.
- ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ฌธ์์ด์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ์ฌ ์ค์๊ฐ ๋์ค๋ ๋ถ๋ถ์ ์ค์์ต๋๋ค.
// ./src/components/Description.jsx
const cardType = {
product: "Product",
category: "Category",
brand: "Brand",
exhibition: "Exhibition",
};- ๊ธฐ์กด์๋ ๋ฟ๋ ค์ฃผ๋ ๋ฐ์ดํฐ๋ง ๋ค๋ฅด๊ณ ๋์ผํ ํ์ด์ง๋ฅผ ํ๋์ฝ๋ฉํด์ ๋ถ๋ฆฌํ์ฌ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
- ๋ฐ๋ผ์ ์ปดํฌ๋ํธ์ ํ์ด์ง์ ์ญํ ์ ๋ถ๋ฆฌํ์ต๋๋ค. ๋ ํ์ด์ง์ ๊ณตํต๋ ๋ถ๋ถ์ ์ปดํฌ๋ํธ๋ก ๋ฝ์๋์ต๋๋ค. ๊ฐ๊ฐ์ ํ์ด์ง๋ ์ปดํฌ๋ํธ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ์ฌ ๋ฟ๋ ค์ฃผ๋ ์ญํ ์ ํ๋๋ก ์์ ํ์ต๋๋ค.
- ์ซ์ ํ์ ์ผ๋ก ํํฐ ์ปดํฌ๋ํธ๋ฅผ ๊ด๋ฆฌํ์ฌ ๋ฟ๋ ค์ค ๋ฐ์ดํฐ๋ฅผ ์ ํ์ต๋๋ค.
const [numState, setNumState] = useState(0);
{numState === 0 &&
state
.filter((item) => item.bookmarked)
.map((item) => (
<li key={item.id}>
<Card data={item} />
</li>
))}- ์ด๋์ ๋ฌธ์ ์ ์ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ ์ฉํ๋์ง๊ฐ ๋ช ํํ์ง ์์์ผ๋ฉฐ, ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฅํ๋ ๋ฐฉ๋ฒ๋ ๋ช ํํ ์๊ธฐ ํ๋ค๋ค๋ ์ ์ ์ ์ ์์์ต๋๋ค. ๊ทธ๋์ ์ซ์๊ฐ ์๋ ์ํ ํ์ ์ ๋ฌธ์์ด๋ก ์์ฑํ์ฌ ๊ด๋ฆฌํ๋๋ก ํ์์ต๋๋ค.
const filterSet = {
all: "์ ์ฒด",
product: "์ํ",
categoryl: "์นดํ
๊ณ ๋ฆฌ",
exhibition: "๊ธฐํ์ ",
brand: "๋ธ๋๋",
};
{filterState === filterSet.all && (
<CardList state={state.slice(0, dataNum)} />
)}- ๋ค์๊ณผ ๊ฐ์ด ๋ฟ๋ ค์ค ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ ํํฐ๋ฅผ ๋ฌธ์์ด๋ก ํ์ฌ ๋ช ํํ ์ฝ๋๋ฅผ ๋ณด๊ณ ์๋๋ฅผ ํ์ ํ ์ ์๋๋ก ํ์์ต๋๋ค.