코지 코더 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)
댓글 남기기