[React] 4. 상태 관리

문정준's avatar
Aug 20, 2025
[React] 4. 상태 관리

1. npm 라이브러리 설치

1) react-router-dom

notion image
  • 복사 버튼을 누른 후 콘솔에 붙여넣어서 설치
notion image
 

2) react-redux

notion image
notion image
 

3) styled-components

notion image
notion image
 

2. Cursor 플러그인 설치

  • Styled Components 설치
notion image
 

3. 화면 작성

  • App 내부에 Navigation bar를 위한 Nav를 설정
    • src/components/Nav.js
import React from 'react'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; export default function Nav() { return ( <NavStyle> <NavLink to={'/'}></NavLink> <NavLink to={'/about'}>소개</NavLink> <NavLink to={'/login'}>로그인</NavLink> </NavStyle> ); } // styled components -> 태그에 css를 부여해서 스타일 지정 가능 const NavStyle = styled.div` display: flex; justify-content: space-between; align-items: center; background-color: lightgray; padding: 10px; `; // 내가 만들었거나 외부 태그는 괄호 안에 넣어서 서식 const NavLink = styled(Link)` margin-right: 10px; text-decoration: none; `;
💡

Link

  • HTML의 a 태그와 같은 하이퍼링크 태그 동작을 하나, 실제 동작은 다름
  • a 태그는 해당 주소로 리다이렉션을 통한 화면 전환
  • Link 태그는 주소를 통해 페이지의 컴포넌트를 변경해서 다시 그림
💡

styled

  • 태그에 css를 부여해서 새로운 태그로 만들 수 있는 라이브러리
  • HTML 태그일 경우 .태그명, 외부 태그 및 직접 만든 태그일 경우 (태그명) 이후 서식 적용
  • 서식은 백틱 사이에 작성
 
  • App.js
import { BrowserRouter, Route, Routes } from 'react-router-dom'; import './App.css'; import Nav from './components/nav'; import Home from './pages/home'; import About from './pages/about'; import Login from './pages/login'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/login" element={<Login />} /> </Routes> <hr /> <Nav /> <h1>Body</h1> </BrowserRouter> ); } export default App;
💡

BrowserRouter, Routes & Route

  • 주소를 통한 이동이 가능하게 만들어주는 태그
  • Routes 태그 안에 해당 주소에 대한 요소를 추가할 수 있음
  • 실제 페이지는 App.js 내부에서만 작동하는 Single-Page-Rendering
 
  • React도 화면에서 상태를 관리할 수 있음
    • /pages/home.js
import React, { useState } from 'react'; export default function Home() { const [num, setNum] = useState(0); console.log('rendered'); function add() { let newNum = num + 1; setNum(newNum); } function minus() { let newNum = num - 1; setNum(newNum); } return ( <div> <div>상태관리연습</div> <div>{num}</div> <button onClick={add}>+1</button> <button onClick={minus}>-1</button> <hr /> </div> ); }
💡

상태 관리

  • onClick에서 함수를 전달 받아 num이라는 상태를 변경
  • useState를 이용해 내부의 num 상태를 설정
    • setNum으로 num의 상태를 변경
  • 화면에서 상태 관리도 가능하지만, 제일 좋은 건 따로 컴포넌트 등을 만들어 관리하는 것
 
notion image
 
 
💡

React 주의 사항

  • 태그 + 스타일을 함께 서식한 컴포넌트를 재사용할 것
    • 스타일을 계속 재사용하면 유지보수가 어려움
    • 태그와 스타일을 묶어서 단독의 태그(컴포넌트)를 만들고, 그걸 재사용하는 것이 좋음
 
 
 
  • 주소 이동 시 body를 넘길 수 있음
  • App.js
import { BrowserRouter, Route, Routes } from 'react-router-dom'; import './App.css'; import Nav from './components/Nav'; import Home from './pages/Home'; import About from './pages/About'; import Login from './pages/Login'; import Design from './pages/Design'; function App() { return ( <BrowserRouter> <Nav /> <hr /> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/login" element={<Login />} /> <Route path="/design" element={<Design user={{ id: 1, username: 'cos' }} />} /> </Routes> <h1>Body</h1> </BrowserRouter> ); } export default App;
  • /pages/Design.js
import React from 'react'; import styled from 'styled-components'; export default function Design(props) { const { user } = props; return ( <div> {user.username == 'ssar' ? ( <MyBlueBox>ssar</MyBlueBox> ) : ( <MyRedBox>cos</MyRedBox> )} <MyBox user={user} title={'제목1'}> 유저네임 : {user.username} </MyBox> </div> ); } const MyRedBox = styled.div` color: red; `; const MyBlueBox = styled.div` color: blue; `; const MyBox = styled.div` color: ${props => (props.user.username == 'ssar' ? 'blue' : 'red')}; `;
💡

Props & Props passing in Styled Components

  • props를 활용하면 주소에서 내가 넘길 body를 작성해서 넘길 수 있음
  • props의 속성을 이용해서 태그의 스타일을 바꿀 수 있는 props passing을 styled components에서 지원
 
  • /pages/About.js
import React, { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; export default function About() { const [count, setCount] = useState(10); const [number, setNumber] = useState(500); const navigate = useNavigate(); useEffect(() => { console.log('useEffect 실행됨'); // cleanup (상태 삭제 시 실행행) return () => { console.log('useEffect 종료됨'); }; }, [count, number]); function addCount() { setCount(count + 1); } function addNumber() { setNumber(number + 1); } function moveLogin() { navigate('/login'); } function moveInfo() { navigate('/info/10/good/20?page=5'); } return ( <div> <h1>{count}</h1> <h1>{number}</h1> <button onClick={addCount}>카운트 증가</button> <button onClick={addNumber}>넘버 증가</button> <button onClick={moveLogin}>로그인 페이지 이동</button> <button onClick={moveInfo}>인포 페이지 이동</button> </div> ); }
💡

useEffect

  • 첫 시작 시 상태를 초기화할 수 있는 함수 = initState
  • 시작 시 실행할 함수, 상태로 관리할 값을 지정 가능 (배열)
  • 함수 부분에 return 작성 : 상태가 사라지면 해당 함수를 실행
💡

onNavigate

  • 함수를 반환하여 주소를 이동할 수 있게 해주는 함수
 
  • PathVariable, QueryString을 넘겨 처리할 수도 있음
    • /pages/Info.js
import React from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; export default function Info() { const { id, goodId } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); let page = searchParams.get('page'); return ( <div> <h1>{id}</h1> <h1>{goodId}</h1> <h2>{page}</h2> </div> ); }
  • App.js
import { BrowserRouter, Route, Routes } from 'react-router-dom'; import './App.css'; import Nav from './components/Nav'; import Home from './pages/Home'; import About from './pages/About'; import Login from './pages/Login'; import Design from './pages/Design'; import Info from './pages/Info'; function App() { return ( <BrowserRouter> <Nav /> <hr /> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/login" element={<Login />} /> <Route path="/info/:id/good/:goodId" element={<Info />} /> <Route path="/design" element={<Design user={{ id: 1, username: 'cos' }} />} /> </Routes> <h1>Body</h1> </BrowserRouter> ); } export default App;
💡

useParams & useSearchParams

  • useParams : PathVariable을 가공할 수 있는 함수
    • 객체 구조 분해를 이용하여 선언 - useParams는 객체로 멤버 관리
  • useSearchParams : QueryString을 가공할 수 있는 함수
    • 배열 비구조화 할당을 이용하여 선언 - useSearchParams는 배열 제공
 
notion image
notion image
notion image
 
 
Share article

sxias