나는 많이 멍청해서 남들이 하지 말라는 거 다 하고 나서 깨닫는다.
아, 하면 안 되는 구나!
나말고 누군가의 말을 신용하지 못하는 것도 있지만 직접 겪어봐야 깨닫는 이상한 성격때문에 어쩔 수가 없다.
그래서 결론은! 리액트 진짜 뭔지 좆도 이해 못해서 블로그 만들면서 깨달아보려고 한다.
ㅎㅎ... 민망하지만... 그냥 구조만 잡아봤다. 디자인은 진행하면서 생각해보려고 한다.
아니면 원래 만들었던 블로그 디자인 그대로 가져가면서 싱글 페이지 앱으로 만들까, 아직 고민중이다.
npx create-react-app 프로젝트이름
cd 프로젝트 이름
yarn start
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
<App>
이라는 이름을 가진 함수 컴포넌트인가 보다.
화면이 잘 뜨는 것을 확인했으니까 필요없는 <div className="App">
아래 코드들은 다 지워야겠다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App
컴포넌트를 불러와 여기서 사용하고 있다. 그리고 'root'
라는 곳에 App
컴포넌트를 render 하라는 것 같은데 'root'
는 어디에 있을까?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
body
태그 아래에 <div id="root">
를 발견했다. 아마 여기에 App
컴포넌트를 그리는 것 같은데, 그러면 root
를 모든 컴포넌트의 부모라고 할 수도 있겠다.
Router
를 이용하여 블로그를 만들 예정이기 때문에 Router
만 관리하는 컴포넌트가 있으면 좋을 것 같다고 생각한다.
그리고 최대한 App.js
파일은 깔끔하게 유지하기 위해 다 작게 작게 쪼개서 관리해보려고 한다.
위와 같은 폴더 구조로 만들 예정인데 살짝 달라질 수도 있을 것이다.
웹과 앱에서의 라우팅은 사용자가 원하는 url에 맞는 화면을 보여주는 것을 말한다.
npm i react-router
npm i react-router-dom
터미널에 입력해준다. 여기서 i
는 install을 뜻한다.
줄여 말하기 좋아하는 개발자들 ... 줄좋개
오 둘 다 잘 설치되었다.
router 버전 6을 사용할 것이다. 생각보다 많이 바뀐 듯하다.
아래의 글을 많이 참고하여 블로그를 만들 예정이다!
정말 진부하게도 about
, contact
, start
메뉴를 만들 것이다. 조금 더 틀이 잡히고 나서 메뉴의 타이틀을 바꾸려고 한다.
❗️ 컴포넌트 이름의 첫 글자는 꼭 대문자로 !
import React from "react";
export default function AboutPage() {
return (
<h1>About</h1>
);
}
import React from "react";
export default function ContactPage() {
return <h1>Contact</h1>;
}
import React from "react";
export default function StartPage() {
return <h1>start</h1>;
}
Router
를 사용하려면 모든 링크를 <BrowserRouter>
로 감싸주어야 한다.
<BrowserRouter>
안에는 Routes
와 Route
가 있다.
Routes
는 Route
를 감싼다.
정리하자면, router
의 기본 생김새는 아래와 같다.
import { BrowserRouter, Routes, Route } from "react-router-dom"
<BrowserRouter>
<Routes>
<Route />
</Routes>
</BrowserRouter>
<BrowserRouter>
: nav, 페이지 같은 모든 것들을 이것으로 감싸야 한다.
Routes
: 여러 개의 Route
를 감싸고 핸들링해주는 컴포넌트이다.
Route
: <Route>
태그 안에는 path
와 그에 맞추어 보여줄 컴포넌트
를 설정할 수 있다.
<Route path="url" element={<컴포넌트이름 />} />
예) <Route path="/" element={<Start />} />
❗️ path가 /
일 때, <Start />
라는 element
를 렌더하라는 뜻이다.
<nav>
<Link to='/'>Start</NavLink>
<Link to='/about'>About</Link>
<Link to='/contact'>Contact</Link>
</nav>
여기서 Link
는 <a href="/">
와 비슷하게 쓰이고 비슷한 일을 한다.
다른 점이 있다면 <a>
태그는 브라우저가 refresh 되면서 페이지 이동이 되는데, <Link>
는 refresh 되지 않고 페이지 간 이동이 가능하다.
| 실행화면
페이지가 refresh 되지 않으면서 url만 바뀌는 것을 확인할 수 있다.
Link
가 아닌 NavLink
를 쓰면 조금 더 스타일 입히기가 편해진다.
리액트에서 자동적으로 NavLink
에 onClick()
이벤트도 주고 className도 지정해주어서 따로 className을 지정한다던가 이벤트 같은 걸 주지 않아도 된다.
<nav>
<NavLink to='/'>Start</NavLink>
<Link to='/about'>About</Link>
<Link to='/contact'>Contact</Link>
</nav>
비교해보기 위해서 /
(Start 컴포넌트) 만 <NavLink>
로 바꾸었고, 나머지는 <Link>
로 놔두었다.
<NavLink to='/'>Start</NavLink>
Start 메뉴를 클릭했을 때start 에 class="active"
가 생겼다.
<Link to='/contact'>Contact</Link>
Contact 메뉴를 클릭했을 때start의 class="active"
가 사라지고, contact에는 변화가 없다.
<NavLink>
를 사용하면 active 일 때 메뉴 버튼의 배경색을 다르게 한다던가, 그런 식으로 편하게 스타일을 입힐 수 있다.
++ className 에 함ㅁ수도 쓸 수 있다.
<NavLink className={({ isActive }) => "nav-link" + (isActive ? " click" : "")} to='/'>
Start
</NavLink>
import React from "react";
import { BrowserRouter, Routes, Route, NavLink } from "react-router-dom";
import AboutPage from "./pages/About/AboutPage";
import ContactPage from "./pages/Contact/ContactPage";
import StartPage from "./pages/Start/StartPage";
export default function Router() {
return (
<BrowserRouter>
<nav>
<NavLink className={({ isActive }) => "nav-link" + (isActive ? " click" : "")} to='/'>
Start
</NavLink>
<NavLink className={({ isActive }) => "nav-link" + (isActive ? " click" : "")} to='/about'>
About
</NavLink>
<NavLink className={({ isActive }) => "nav-link" + (isActive ? " click" : "")} to='/contact'>
Contact
</NavLink>
</nav>
<Routes>
<Route exact path='/' element={<StartPage />} />
<Route path='/about' element={<AboutPage />} />
<Route path='/contact' element={<ContactPage />} />
</Routes>
</BrowserRouter>
);
}
Rouer.jsx
를 이렇게 완성시켰다.
import "./App.css";
import Router from "./Router";
function App() {
return (
<div className='App'>
<Router />
</div>
);
}
export default App;
App.js
에 <Router />
컴포넌트를 불러왔다.
| 실행화면
메뉴를 누르면 메뉴에 해당하는 컴포넌트의 내용이 refresh 되지 않고 보여진다.
왕 신기하다!
아직 스타일을 먹이지 않아서 이상하게 보이는데 앞으로 점점 다듬으면서 변화를 줄 생각이다!
저도 아무것도 모르는 상태로 리액트로 블로그 좀 만들어보려다 들어오게되었는데 재밌게 잘 봤습니다 ㅎㅎㅎ