코지 코더 Kossie Code
동영상 30개조회수 88,303회최종 업데이트: 2021. 4. 6.
https://www.youtube.com/playlist?list=PLB7CpjPWqHOuf62H44TMkMIsqfkIzcEcX
vscode 확장 패키지 추가
1. - Auto Import - ES6, TS, JSX, TSX
2. - Reactjs code snippets
3. - ESLint
4. - Prettier - Code formatter
Visual Studio Code 폴더/파일 아이콘 변경하기
리액트 프로젝트 생성
npx create-react-app 경로
예) npx create-react-app E:\react-app2
클릭 => 21. React router 작동 원리 알아보기
방법 1) Router.js 에서 중첩 라우터를 사용하고, 중첩 라우터에서 Outlet 컴포넌트 사용
// Router.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Web from "../Pages/Web";
import WebPost from "../Pages/WebPost";
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="web/*" element={<Web />}>
<Route path=":id" element={<WebPost />} />
</Route>
</Routes>
</BrowserRouter>
);
};
export default Router;
// Web.js
import React from "react";
import { Link, Routes, Route, Outlet } from "react-router-dom";
import WebPost from "./WebPost";
const Web = () => {
return (
<div>
<h1>This is Web</h1>
<ul>
<li>
<Link to="1">Post #1</Link>
</li>
<li>
<Link to="2">Post #2</Link>
</li>
<li>
<Link to="3">Post #3</Link>
</li>
<li>
<Link to="4">Post #4</Link>
</li>
</ul>
<Outlet />
</div>
);
};
export default Web;
export default Web;
// --------------------------------------------------------------------------------
// WebPost.js
import React from "react";
const WebPost = () => {
return <div>This is 포스트</div>;
};
export default WebPost;
- 위 코드와 같이 Router.js에서 자식 태그로 중첩하는 라우터를 기재하고,
Web.js에서 Outlet 라이브러리를 통해 가져옵니다. - exact 안 쓰는 대신 /*가 필수입니다.
방법 2) 곧바로 기재
// Router.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Web from "../Pages/Web";
const Router = () => {
return (
<BrowserRouter>
<Header />
<Routes>
<Route path="web/*" element={<Web />} />
</Routes>
</BrowserRouter>
);
};
export default Router;
// Web.js
import React from "react";
import { Link, Routes, Route} from "react-router-dom";
import WebPost from "./WebPost";
const Web = () => {
return (
<div>
<h1>This is Web</h1>
<ul>
<li>
<Link to="1">Post #1</Link>
</li>
<li>
<Link to="2">Post #2</Link>
</li>
<li>
<Link to="3">Post #3</Link>
</li>
<li>
<Link to="4">Post #4</Link>
</li>
</ul>
<Routes>
<Route path=":id" element={<WebPost />} />
</Routes>
</div>
);
};
export default Web;
// --------------------------------------------------------------------------------
// WebPost.js
import React from "react";
const WebPost = () => {
return <div>This is 포스트</div>;
};
export default WebPost;
- 위 코드와 같이 Outlet 없이 곧바로 Routes , Route로 기재할 수 있습니다.
출처:
[React] react-router-dom v6 업그레이드 되면서 달라진 것들
샘플
import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import Products from './pages/Products'
import Product1 from "./pages/Product1";
import Product2 from "./pages/Product2";
import Product3 from "./pages/Product3";
import DynamicPage from "./pages/DynamicPage";
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="/products/product1" element={<Product1 />} />
<Route path="/products/product2" element={<Product2 />} />
<Route path="/products/product3" element={<Product3 />} />
<Route path="/products/:id" element={<DynamicPage/>} />
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
클릭 => 22. NavLink 사용하기
<NavLink> https://v5.reactrouter.com/web/api/NavLink
<NavLink
to="/faq"
className={isActive =>
"nav-link" + (!isActive ? " unselected" : "")
}
>
FAQs
</NavLink>
<NavLink to="/faq" activeClassName="selected"> FAQs </NavLink
<NavLink
to="/faq"
style={isActive => ({
color: isActive ? "green" : "blue"
})}
>
FAQs
</NavLink>
<NavLink
to="/faq"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
FAQs
</NavLink>
<NavLink exact to="/profile"> Profile </NavLink>
index.css
.navbar .active , .navbar-nav .active{
color: rgb(46, 122, 214) !important;
}
Navbar.js
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { Link, NavLink } from "react-router-dom";
const Navbar = () => {
return (
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<NavLink className="navbar-brand" to="/" >Home</NavLink>
<button className="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNavAltMarkup">
<div className="navbar-nav">
{/*현재 버전의 부스트스랩 4.6 에서 activeClassName="active" 사용하지 않아도 된다.
activeClassName="active" 사용시 오류
*/}
{/*
<NavLink className="nav-link" to="/movies">Movies
<span className="sr-only">(current)</span>
</NavLink>
<NavLink className="nav-link" to="/users">Users</NavLink>
<NavLink className="nav-link" activeClassName="active" to="/movies">Movies
<span className="sr-only">(current)</span>
</NavLink>
<NavLink className="nav-link" activeClassName="active" to="/users">Users</NavLink> */}
<NavLink className={(navData) => (navData.isActive ? "nav-link active" : 'nav-link')} to="/movies">Movies
<span className="sr-only">(current)</span>
</NavLink>
<NavLink className={(navData) => (navData.isActive ? "nav-link active" : 'nav-link')} to="/users">Users</NavLink>
</div>
</div>
</nav >
);
};
export default Navbar;
클릭 => 23.유저 데이터 받아오기
설치 : axios 설치
$ npm i axios
https://www.npmjs.com/package/axios
가짜 테스트 API = > http://jsonplaceholder.typicode.com/
axios 요청(request) 파라미터 옵션
- method : 요청방식. (get이 디폴트)
- url : 서버 주소
- baseURL : url을 상대경로로 쓸대 url 맨 앞에 붙는 주소.
- 예를들어, url이 /post 이고 baseURL이 https://some-domain.com/api/ 이면,
https://some-domain.com/api/post로 요청 가게 된다.
- 예를들어, url이 /post 이고 baseURL이 https://some-domain.com/api/ 이면,
- headers : 요청 헤더
- data : 요청 방식이 'PUT', 'POST', 'PATCH' 해당하는 경우 body에 보내는 데이터
- params : URL 파라미터 ( ?key=value 로 요청하는 url get방식을 객체로 표현한 것)
- timeout : 요청 timeout이 발동 되기 전 milliseconds의 시간을 요청. timeout 보다 요청이 길어진다면, 요청은 취소되게 된다.
- responseType : 서버가 응답해주는 데이터의 타입 지정 (arraybuffer, documetn, json, text, stream, blob)
- responseEncoding : 디코딩 응답에 사용하기 위한 인코딩 (utf-8)
- transformRequest : 서버에 전달되기 전에 요청 데이터를 바꿀 수 있다.
- 요청 방식 'PUT', 'POST', 'PATCH', 'DELETE' 에 해당하는 경우에 이용 가능
- 배열의 마지막 함수는 string 또는 Buffer, 또는 ArrayBuffer를 반환합
- header 객체를 수정 가능
- transformResponse : 응답 데이터가 만들어지기 전에 변환 가능
- withCredentials : cross-site access-control 요청을 허용 유무. 이를 true로 하면 cross-origin으로 쿠키값을 전달 할 수 있다.
- auth : HTTP의 기본 인증에 사용. auth를 통해서 HTTP의 기본 인증이 구성이 가능
- maxContentLength: http 응답 내용의 max 사이즈를 지정하도록 하는 옵션
- validateStatus : HTTP응답 상태 코드에 대해 promise의 반환 값이 resolve 또는 reject 할지 지정하도록 하는 옵션
- maxRedirects : node.js에서 사용되는 리다이렉트 최대치를 지정
- httpAgent / httpsAgent : node.js에서 http나 https를 요청을 할때 사용자 정의 agent를 정의하는 옵션
- proxy : proxy서버의 hostname과 port를 정의하는 옵션
- cancelToken : 요청을 취소하는데 사용되어 지는 취소토큰을 명시]
/* axios 파라미터 문법 예시 */
axios({
method: "get", // 통신 방식
url: "www.naver.com", // 서버
headers: {'X-Requested-With': 'XMLHttpRequest'} // 요청 헤더 설정
params: { api_key: "1234", langualge: "en" }, // ?파라미터를 전달
responseType: 'json', // default
maxContentLength: 2000, // http 응답 내용의 max 사이즈
validateStatus: function (status) {
return status >= 200 && status < 300; // default
}, // HTTP응답 상태 코드에 대해 promise의 반환 값이 resolve 또는 reject 할지 지정
proxy: {
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
}, // proxy서버의 hostname과 port를 정의
maxRedirects: 5, // node.js에서 사용되는 리다이렉트 최대치를 지정
httpsAgent: new https.Agent({ keepAlive: true }), // node.js에서 https를 요청을 할때 사용자 정의 agent를 정의
})
.then(function (response) {
// response Action
});
axios GET
const axios = require('axios'); // node.js쓸때 모듈 불러오기
// user에게 할당된 id 값과 함께 요청을 합니다.
axios.get('/user?ID=12345')
.then(function (response) {
// 성공했을 때
console.log(response);
})
.catch(function (error) {
// 에러가 났을 때
console.log(error);
})
.finally(function () {
// 항상 실행되는 함수
});
// 위와는 같지만, 옵션을 주고자 할 때는 이렇게 요청을 합니다.
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// always executed
});
// async/await 를 쓰고 싶다면 async 함수/메소드를 만듭니다.
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
axios POST
axios.post("url", {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
// response
}).catch(function (error) {
// 오류발생시 실행
})
axios Delete
axios.delete('/user?ID=12345',{
data: {
post_id: 1,
comment_id: 13,
username: "foo"
}
})
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
axios PUT
axios.put("url", {
username: "",
password: ""
})
.then(function (response) {
// response
}).catch(function (error) {
// 오류발생시 실행
})
출처: https://inpa.tistory.com/entry/AXIOS-????-설치-사용 [???????? Dev Scroll:티스토리]
Users.js
import React, { useEffect } from 'react';
import axios from "axios";
const Users = () => {
useEffect(() => {
axios.get("http://jsonplaceholder.typicode.com/users")
.then(res => {
console.log(res);
})
}, []);
return (
<h1>Users</h1>
);
};
export default Users;
클릭 => 24.유저 데이터 화면에 출력하기

UserList.js
import React from 'react';
const UserList = ({ users }) => {
console.log(users);
return (
<div>
{users.map((user) => {
return (
<div key={user.id}>
{user.name}
</div>
);
})}
</div>
);
};
export default UserList;
Users.js
import React, { useEffect, useState } from 'react';
import axios from "axios";
import UserList from './../components/UserList';
const Users = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("http://jsonplaceholder.typicode.com/users")
.then(res => {
// console.log("1.res.data :", res.data);
setUsers(res.data);
})
}, []);
useEffect(() => {
//console.log("2.users :", users);
}, [users]);
return (
<>
<h1>Users</h1>
<UserList users={users} />
</>
);
};
export default Users;
클릭 => 25.유저 데이터 화면에 출력하기 2

App.js 에 <div className='container'> 추가
import Movie from './components/Movie';
import { useState } from 'react';
import MovieForm from './components/MovieForm';
import Navbar from './components/Navbar';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import PageMovies from './pages/PageMovies';
import Users from './pages/Users';
function App() {
const [movies, setMovies] = useState([]);
const removeMovie = (id) => {
setMovies(movies.filter((movie) => movie.id !== id));
}
const renderMovies = movies.length ? movies.map((movie) => {
return <Movie key={movie.id} movie={movie} removeMovie={removeMovie} />
}) : "추가된 영화가 없습니다. ";
const addMovie = (movie) => {
setMovies([...movies, movie]);
}
return (
<div className="App">
<div className='container'>
<Navbar />
<Routes>
<Route path='/' element={<h1>Home</h1>}></Route>
<Route path='/movies' element={<PageMovies addMovie={addMovie} renderMovies={renderMovies} />}></Route>
<Route path='/users' element={<Users />}></Route>
</Routes>
</div>
</div >
);
}
export default App;
UserList.js
import React from 'react';
const UserList = ({ users }) => {
console.log(users);
return (
<div>
{
users.map((user) => {
return (
<div className="card mb-2" key={user.id}>
<div className="card-body p-3">
{user.name}
</div>
</div>
);
})
}
</div >
);
};
export default UserList;
클릭 => 26.로딩 Spinner 추가하기
부트스트랩 Spinners => https://getbootstrap.com/docs/4.6/components/spinners/
Spinner.js
import React from 'react';
const Spinner = () => {
return (
<div className='d-flex justify-content-center'>
<div className="spinner-border"
style={{
width: '3rem',
height: '3rem'
}}
role="status">
<span className="sr-only">Loading...</span>
</div>
</div>
);
};
export default Spinner;
Users.js
import React, { useEffect, useState } from 'react';
import axios from "axios";
import UserList from './../components/UserList';
import Spinner from '../components/Spinner';
const Users = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
axios.get("http://jsonplaceholder.typicode.com/users")
.then(res => {
// console.log("1.res.data :", res.data);
setUsers(res.data);
setLoading(false);
})
}, []);
useEffect(() => {
//console.log("2.users :", users);
}, [users]);
return (
<>
<h1>Users</h1>
{loading ? <Spinner /> :
<UserList users={users} />
}
</>
);
};
export default Users;
클릭 => 27. Home/Movies 페이지 컴포넌트 만들기
Home.js
import React from 'react';
const Home = () => {
return (
<h1>Home</h1>
);
};
export default Home;
Movies.js
import React, { useState } from 'react';
import MovieForm from '../components/MovieForm';
import Movie from './../components/Movie';
const Movies = () => {
const [movies, setMovies] = useState([]);
const removeMovie = (id) => {
setMovies(movies.filter((movie) => movie.id !== id));
}
const renderMovies = movies.length ? movies.map((movie) => {
return <Movie key={movie.id} movie={movie} removeMovie={removeMovie} />
}) : "추가된 영화가 없습니다. ";
const addMovie = (movie) => {
setMovies([...movies, movie]);
}
return (
<div>
<h1>Movie list</h1>
<MovieForm addMovie={addMovie} />
<br /><br />
{renderMovies}
</div>
);
};
export default Movies;
App.js
import Navbar from './components/Navbar';
import { Routes, Route } from 'react-router-dom';
import Movies from './pages/Movies';
import Users from './pages/Users';
import Home from './pages/Home';
function App() {
return (
<div className="App">
<div className='container'>
<Navbar />
<Routes>
<Route path='/' element={<Home />}></Route>
<Route path='/movies' element={<Movies />}></Route>
<Route path='/users' element={<Users />}></Route>
</Routes>
</div>
</div >
);
}
export default App;
클릭 => 28.routes 파일 만들기
routes.js
/* eslint-disable import/no-anonymous-default-export */
import Movies from './pages/Movies';
import Users from './pages/Users';
import Home from './pages/Home';
export default [
{
path: '/',
element: <Home />
},
{
path: '/movies',
element: <Movies />
},
{
path: '/users',
element: < Users />
},
]
App.js
import Navbar from './components/Navbar';
import { Routes, Route } from 'react-router-dom';
import routes from './routes';
function App() {
return (
<div className="App">
<div className='container'>
<Navbar />
<Routes>
{routes.map((route) => {
return <Route key={route.path} path={route.path} element={route.element}></Route>
})}
</Routes>
</div>
</div >
);
}
export default App;
클릭 => 29. user 페이지 라우트 추가
routes.js 에 추가
/* eslint-disable import/no-anonymous-default-export */
import Movies from './pages/Movies';
import Users from './pages/Users';
import User from './pages/User';
import Home from './pages/Home';
export default [
{
path: '/',
element: <Home />
},
{
path: '/movies',
element: <Movies />
},
{
path: '/users',
element: <Users />
},
{
path: '/users/:id',
element: <User />
},
]
User.js
import React, { useEffect, useState } from 'react';
import axios from "axios";
import UserList from '../components/UserList';
import Spinner from '../components/Spinner';
import { useParams } from 'react-router-dom';
const User = () => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const { id } = useParams();
console.log("id : ", id);
useEffect(() => {
axios.get("http://jsonplaceholder.typicode.com/users/" + id)
.then(res => {
console.log("1.res.data :", res.data);
setUser(res.data);
setLoading(false);
})
}, []);
useEffect(() => {
if (user !== null) {
console.log("2.user :", user.name);
}
}, [user]);
return (
<>
<h1>Users 정보</h1>
{loading ? <Spinner />
: null
}
</>
);
};
export default User;
클릭 => 30.user 페이지


User.js
import React, { useEffect, useState } from 'react';
import axios from "axios";
import UserList from '../components/UserList';
import Spinner from '../components/Spinner';
import { useParams } from 'react-router-dom';
const User = () => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const { id } = useParams();
console.log("id : ", id);
useEffect(() => {
axios.get("http://jsonplaceholder.typicode.com/users/" + id)
.then(res => {
console.log("1.res.data :", res.data);
setUser(res.data);
setLoading(false);
})
}, []);
useEffect(() => {
if (user !== null) {
console.log("2.user :", user.name);
}
}, [user]);
const userDetail = loading ? <Spinner /> : (
<div>
<div>{user.name}</div>
<div>{user.email}</div>
<div>{user.phone}</div>
</div>
);
return (
<>
<h1>Users 정보</h1>
{userDetail}
</>
);
};
export default User;
UserList.js
링크 적용
import React from 'react';
import { Link } from 'react-router-dom';
const UserList = ({ users }) => {
console.log(users);
return (
<div>
{
users.map((user) => {
return (
<div className="card mb-2" key={user.id}>
<div className="card-body p-3">
<Link to={`/users/${user.id}`}>{user.name}</Link>
</div>
</div>
);
})
}
</div >
);
};
export default UserList;
소스 : https://github.com/braverokmc79/Rreact-KossieCoder















댓글 ( 4)
댓글 남기기