코딩애플 강의를 통해 배운 리액트를 정리한 글입니다.
2025년 2월 04일
Part 2 : 쇼핑몰 프로젝트
// React Bootstrap 설치
npm install react-bootstrap bootstrap
// 글로벌 스타일 적용 (index.html)
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous"
/>
or
// 각 파일에서 Bootstrap 스타일 적용
import 'bootstrap/dist/css/bootstrap.min.css';
// 예제: 버튼 적용
import { Button } from "react-bootstrap";
<Button>버튼</Button>
// jsx상에서 이미지 적용
import 이미지 from "/경로";
<div style={{background : 'url(' + import로가져온이미지 + ')'}}></div>
<div style={{ background: `url(${이미지})` }}></div>
// css상에서 이미지 적용
background-image: url("/경로");
//public상에서 이미지 가져오기
<img src="/이미지경로"/>
//해결법
<img src={process.env.PUBLIC_URL + "/이미지명"} />
//data.js
export default data;
export { data1, data2, data3 };
//App.jsx
import data from "/경로";
import { data1, data2, data3 } from "/경로";
// router설치
npm install react-router-dom@6
//main.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.jsx";
import { BrowserRouter } from "react-router-dom";
createRoot(document.getElementById("root")).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);
//App.jsx
import { Routes, Route, Link } from "react-router-dom";
<Routes>
<Route path="/detail" element={<div>상세페이지임</div>} />
<Route path="/about" element={<div>어바웃페이지임</div>} />
</Routes>
<Link to="/">홈</Link>
React Router에서 페이지 이동을 도와주는 훅(Hook)입니다.
import { useNavigate } from "react-router-dom";
const MyComponent = () => {
let navigate = useNavigate();
return <button onClick={() => navigate("/경로")}>이동</button>;
};
navigate(1); // 앞으로 한 페이지 이동
navigate(-1); // 뒤로 한 페이지 이동
존재하지 않는 경로에 대한 처리를 위해 *을 사용합니다.
<Route path="*" element={<div>404 - 페이지를 찾을 수 없습니다.</div>} />
📌 *은 모든 경로를 의미하며, 기존에 정의된 경로와 일치하지 않을 경우 해당 컴포넌트가 렌더링된다.
Outlet을 사용하면 부모 컴포넌트 안에서 자식 컴포넌트가 렌더링된다.import { Routes, Route, Outlet } from "react-router-dom";
const About = () => {
return (
<div>
<h2>About 페이지</h2>
<Outlet />
</div>
);
};
const App = () => {
return (
<Routes>
<Route path="/about" element={<About />}>
<Route path="member" element={<div>멤버 페이지</div>} />
</Route>
</Routes>
);
};
/about으로 이동하면 About 페이지만 보입니다./about/member로 이동하면 About 페이지 + 멤버 페이지가 함께 렌더링됩니다.Outlet이 있는 위치에 중첩된 컴포넌트가 표시됩니다./detail/123
<Route path="/detail/:id" element={<Detail />} />
import { useParams } from "react-router-dom";
const Detail = () => {
let { id } = useParams(); // 현재 URL의 파라미터 값 가져오기
return <div>현재 상품 ID: {id}</div>;
};
//설치
npm install styled-components
//임포트
import styled from 'styled-components'
//적용예시
let Button = styled.button `
background : yellow `
<Button></Button>
//적용예시2
let Button = styled.button `
background : ${props => props.bg} `
<Button bg="blue"></Button>
컴포넌트.module.css 파일 만들면 전염안됨mount, update시 코드를 실행해준다React.StrictMode를 없애면 2번 호출 안됨useEffect(() => {
코드;
});
//특정값이 변경됬을 때만 실행이 되게 하려면
useEffect(() => {}, [특정값]);
//처음 mount됬을 때만 1회실행됨
useEffect(() => {}, []);
//useEffect가 실행되기전에 코드를 실행
useEffect(() => {
return () => {
코드;
};
}, []);
// 이런건 대부분 기존 데이터를 전부 깔끔하게 지우고 새로시작할 때 사용한다
// 타이머같은 경우에는 변수에 타이머를 저장한 후 return 에 clearTimeout(변수)
// 이렇게 작성해도된다
//특정값이 변경됬을 때만 실행이 되게 하려면
npm install axios
//import
import axios from "axios";
//실행
axios.get('url쓰기').then((결과)=>{
console.log(결과.data)
})
Promise.all([a, b]).then(() => {});
// 삼항 연산자
{tab == 0 : <div>내용0</div>; ? null}
// if문
<TabContent tab={tab}></TabContent>
function TabContent({tab}) {
if (tab === 0) {
return <div>내용0</div>;
}
}
// array
<TabContent tab={tab}></TabContent>
function TabContent({tab}) {
return [ <div>내용0</div>, <div>내용1</div>, <div>내용2</div> ][tab]
}
npm install @reduxjs/toolkit react-redux
import { configureStore } from "@reduxjs/toolkit";
export default configureStore({
reducer: {},
});
import { Provider } from "react-redux";
import store from "./store.js";
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>;
//store.js
import { configureStore, createSlice } from "@reduxjs/toolkit";
let user = createSlice({
name: "user",
initialState: "kim",
});
export default configureStore({
reducer: {
user: user.reducer,
},
});
// name : 'state이름', initialState : 'state값'
// { 작명 : createSlice만든거.reducer }
import { useSelector } from "react-redux";
let a = useSelector((state) => {
return state;
});
---
## 📬 part2-13 리액트에서 탭 UI 만들기
### 🔹 1. 조건식으로 화면에 show hide하는방법
```jsx
// 삼항 연산자
{tab == 0 : <div>내용0</div>; ? null}
// if문
<TabContent tab={tab}></TabContent>
function TabContent({tab}) {
if (tab === 0) {
return <div>내용0</div>;
}
}
// array
<TabContent tab={tab}></TabContent>
function TabContent({tab}) {
return [ <div>내용0</div>, <div>내용1</div>, <div>내용2</div> ][tab]
}
//store.js
let user = createSlice({
name: "user",
initialState: "kim",
reducers: {
changeName(state) {
return "john" + state;
},
},
});
export let { changeName } = user.actions;
//Detail.jsx
import { changeName } from "../store";
funtion Detail() {
let dispatch = useDispatch();
return(
<button
onClick={() => {
dispatch(changeName());
}}
></button>
)
}
increase(state, action) {
state.age += action.payload;
},
//stockSlice.js;
import { createSlice } from "@reduxjs/toolkit";
let stock = createSlice({
name: "stock",
initialState: [10, 11, 12],
});
export default stock;
//store.js;
import { configureStore} from "@reduxjs/toolkit";
import stock from '../stockSlice'
export default configureStore({
reducer: {
stock: stock.reducer,
},
});
function Component() {
if (true) {
return <p>참이면 보여줄 HTML</p>;
} else {
return null;
}
}
function Component() {
return <div>{1 === 1 ? <p>참이면 보여줄 HTML</p> : null}</div>;
}
function Component() {
return <div>{1 === 1 && <p>참이면 보여줄 HTML</p>}</div>;
}
function Component2() {
var user = "seller";
switch (user) {
case "seller":
return <h4>판매자 로그인</h4>;
case "customer":
return <h4>구매자 로그인</h4>;
default:
return <h4>그냥 로그인</h4>;
}
}
function Component() {
var 현재상태 = "info";
return (
<div>
{
{
info: <p>상품정보</p>,
shipping: <p>배송관련</p>,
refund: <p>환불약관</p>,
}[현재상태]
}
</div>
);
}
-사이트를 꺼도 계속해서 남아있음
localStorage.setItem("데이터이름", "데이터");
localStorage.getItem("데이터이름");
localStorage.removeItem("데이터이름");
//array object저장
localStorage.setItem("데이터이름", JSON.stringify({ name: "kim" }));
var a = localStorage.getItem("데이터이름");
var b = JSON.parse(a);
npm install react-query
//main,js
import { QueryClient, QueryClientProvider } from "react-query"
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
~~
</QueryClientProvider>
//app.jsx
import { useQuery } from "react-query";
function App(){
let result = useQuery('작명', ()=>
axios.get('https://codingapple1.github.io/userdata.json')
.then((a)=>{ return a.data })
)
return (
<div>
{ result.isLoading && '로딩중' }
{ result.error && '에러남' }
{ result.data && result.data.name }
</div>
)
}
const Cart = lazy( () => import('./routes/Cart.js') )
<Suspense fallback={ <div>로딩중임</div> }>
<Detail shoes={shoes} />
</Suspense>
let Child = memo(function() {
console.log('재렌더링됨')
return <div>자식임</div>
})
function Cart(){
let [count, setCount] = useState(0)
return (
<Child />
<button onClick={()=>{ setCount(count+1) }}> + </button>
)
}
npx create-react-app 프로젝트명 --template cra-template-pwa
npm install web-vitals
main.js
serviceWorkerRegistration.unregister(); => serviceWorkerRegistration.register();
//설치
npm init -y
npm install express
npm install cors
//실행
node server.js
//server.js;
const express = require("express");
const path = require("path");
const app = express();
app.listen(8080, function () {
console.log("listening on 8080");
});
app.use(express.json());
var cors = require("cors");
app.use(cors());
app.use(express.static(path.join(__dirname, "프로젝트/dist")));
app.get("/", function (요청, 응답) {
응답.sendFile(path.join(__dirname, "/프로젝트/dist/index.html"));
});
app.get(".product", function (요청, 응답) {
응답.json({ name: "black shoes" });
});
app.get("*", function (요청, 응답) {
응답.sendFile(path.join(__dirname, "/프로젝트/dist/index.html"));
});
열심히하자