[fastcampus] Ch4. React Router (2)

productuidev·2022년 3월 7일
0

React Study

목록 보기
6/52
post-thumbnail

패스트캠퍼스 한 번에 끝내는 프론트엔드 개발(Online) 강의 정리


Ch.4 React Router (2)

4. JSX 링크로 라우팅 이동하기 (1)

리액트 애플리케이션 내부에서 페이지 이동하는 방법 (서버에서 새로 받아오지 않고)

1) src/App.js

import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'; // Link 추가
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
import NotFound from './pages/NotFound';

function App() {
	return (
		<BrowserRouter>
		<Link to="/">Home</Link> // Link 컴포넌트 추가
		<Switch>
			<Route path="/profile/:id" component={Profile}  />
			<Route path="/profile" component={Profile}  />
			<Route path="/about" component={About} />
			<Route path="/" exact component={Home} />
			<Route component={NotFound} />
		</Switch>
		</BrowserRouter>
	);
}

export default App;

chrome>network에서 페이지 새로고침 체크

2) src/components/Link.jsx

import { Link } from "react-rounter-dom";

export default function Links() {
	return(
		<ul>
			<li><Link to="/">Home</Link></li>
			<li><Link to="/profile">Profile</Link></li>
			<li><Link to="/profile/1">Profile/1</Link></li>
			<li><Link to="/about">About</Link></li>
			<li><Link to="/about?name=mark">About?name=mark</Link></li>
		</ul>
	);
}

3) src/App.js

import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
import NotFound from './pages/NotFound';
import Links from './components/Links'; // 추가

function App() {
	return (
		<BrowserRouter>
		<Links /> // Links.jsx 가져오기
		<Switch>
			<Route path="/profile/:id" component={Profile}  />
			<Route path="/profile" component={Profile}  />
			<Route path="/about" component={About} />
			<Route path="/" exact component={Home} />
			<Route component={NotFound} />
		</Switch>
		</BrowserRouter>
	);
}

export default App;

5. JSX 링크로 라우팅 이동하기 (2)

<NavLink>
	activeClassName: string
	activeStyle: object
	exact: bool
	strict: bool
	isActive: func
	location: object
	aria-current: string
</NavLink>
  • import { NavLink } from 'react-router-dom';
  • activeClassName, activeStyle 처럼 active 상태에 대한 스타일 지정이 가능합니다. (Links와의 차이점)
  • Route의 path 처럼 동작하기 때문에 exact가 있습니다. (리액트 매칭 알고리즘, 호환관계)

1) src/components/NavLinks.jsx

import { NavLink } from "react-rounter-dom";

export default function NavLinks() {
	return(
		<ul>
			<li><NavLinks to="/">Home</NavLinks></li>
			<li><NavLinks to="/profile">Profile</NavLinks></li>
			<li><NavLinks to="/profile/1">Profile/1</NavLinks></li>
			<li><NavLinks to="/about">About</NavLinks></li>
			<li><NavLinks to="/about?name=mark">About?name=mark</NavLinks></li>
		</ul>
	);
}

2) src/App.js

import { BrowserRouter, Route, Switch, Links } from 'react-router-dom';
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
import NotFound from './pages/NotFound';
import Links from './components/Links';
import NavLinks from './components/NavLinks'; // 추가

function App() {
	return (
		<BrowserRouter>
		<Links />
		<NavLinks /> // 추가
		<Switch>
			<Route path="/profile/:id" component={Profile}  />
			<Route path="/profile" component={Profile}  />
			<Route path="/about" component={About} />
			<Route path="/" exact component={Home} />
			<Route component={NotFound} />
		</Switch>
		</BrowserRouter>
	);
}

export default App;

3) 활성화된 route에 스타일 넣기 activeStyle={activeStyle}

src/components/NavLinks.jsx

import { NavLink } from "react-rounter-dom";

export default function NavLinks() {
	return(
		<ul>
			<li><NavLinks to="/" exact activeStyle={activeStyle}>Home</NavLinks></li>
			<li><NavLinks to="/profile" activeStyle={activeStyle}>Profile</NavLinks></li>
			<li><NavLinks to="/profile/1" activeStyle={activeStyle}>Profile/1</NavLinks></li>
			<li>
				<NavLinks to="/about"
				activeStyle={activeStyle}
				isActive={(match, location) => {
					console.log(location);
					return true;
					// return location.search === "";
				}}>
				About
				</NavLinks>
			</li>
			<li>
				<NavLinks to="/about?name=mark"
				activeStyle={activeStyle}
				isActive = {(match, location) => {
					return location.search === "?name=mark";
				}}>
				About?name=mark
				</NavLinks>
			</li>
		</ul>
	);
}

6. JS로 라우팅 이동하기

보통 리액트가 아닌 경우에는 location.href를 수정해서 경로를 바꿀수 있었지만
그렇게 하게될 경우, 클라이언트사이드(브라우저) 레벨에서 라우팅이 바뀌는 게 아니라
서버에서 데이터를 가지고 와서 다시 페이지를 보여주는 특성이 있기 때문에
그런 방식으로 페이지 이동처리를 하면 안됨
리액트 방식과 동일하게 JS로 라우팅 이동하는 방법 설명

1) src/App.js

import { BrowserRouter, Route, Switch, Links } from 'react-router-dom';
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
import NotFound from './pages/NotFound';
import Links from './components/Links';
import NavLinks from './components/NavLinks';
import Login from './pages/Login'; // 추가

function App() {
	return (
		<BrowserRouter>
		<Links />
		<NavLinks />
		<Switch>
			<Route path="/login" component={Login} /> // 추가
			<Route path="/profile/:id" component={Profile}  />
			<Route path="/profile" component={Profile}  />
			<Route path="/about" component={About} />
			<Route path="/" exact component={Home} />
			<Route component={NotFound} />
		</Switch>
		</BrowserRouter>
	);
}

export default App;

2) pages/Login.jsx 생성

export default function Login(props) {
	console.log(props);

	function login() {
		setTimeout( () => {
			// 페이지를 이동 (서버에서 API를 호출하여 문제가 없는 경우 일정 시간 뒤 페이지가 이동)
			props.history.push('/'); // 1초 뒤 (브라우저의 히스토리에) Home으로 이동
		}
		,1000);
	}

	return(
		<div>
			<h2>Login 페이지 입니다.</h2>
			<button onClick={login}>로그인하기</button>
		</div>
	);
}

3) 리액트 애플리케이션의 규모가 커질 경우

위의 방식으로만 페이지 이동을 구성할 수 없게됨.
Login(props) 하위에 다른 섹션에 로그인 기능이 들어있게 될수도 있음
(실제로 그런 경우가 비일비재)

src/components/LoginButton.jsx 생성

export default function LoginButton() {
	console.log(props);

	function login() {
		setTimeout( () => {
			props.history.push('/')
		}, 1000);
	}

	return <button onClick={login}>로그인하기</button>
}

4) pages/Login.jsx 수정

import LoginButton from '../components/LoginButton'; // 추가

export default function Login(props){ // 인자
	return (
		<div>
			<h2>Login 페이지 입니다.</h2>
			<LoginButton { ... props } /> // 컴포넌트에 props 객체가 내려옴
		</div>
	);
}

에러 방지

props가 3~4단계 밑에 있는 경우 바로 객체가 내려오지 않을 수 있음
에러 방지를 위한 react-router-dom의 해결방법 2가지

해결방법 1 : HOC(higher ordered component) 사용

HOC란?

고차 컴포넌트는 컴포넌트 로직을 재사용하기 위해 사용되고
컴포넌트를 가져와 새 컴포넌트를 반환하는 함수입니다.
즉, 컴포넌트를 인자로 받거나 반환하는 함수입니다.
출처 - https://itprogramming119.tistory.com/entry/React-%EA%B3%A0%EC%B0%A8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%9E%80

컴포넌트에 날개달기

코드를 작성하다보면, 자주 반복해서 작성하게 되는 코드들이 있습니다. 우리는 주로 그러한 것들을 함수화하여 재사용 하곤 하죠. 컴포넌트 또한 비슷하죠. 같은 UI 관련 코드가 재사용 될 수 있다면 우리는 컴포넌트를 만들어서 컴포넌트를 재사용합니다. 자, 그런데 컴포넌트 기능 상에서도, 자주 반복되는 코드들이 나타날 수 있습니다. 소프트웨어 개발 원리 중에서 DRY 라는 개념이 있죠 – 같은 작업을 반복하지 마라 (Don’t repeat yourself). 리액트 컴포넌트를 작성하게 될 때 반복될 수 있는 코드들은, HOC 를 만들어서 해결해줄 수 있습니다. HOC 는, 하나의 함수인데요, 함수를 통하여 컴포넌트에 우리가 준비한 특정 기능을 부여합니다.
출처 - https://velopert.com/3537

1) pages/Login.jsx 수정

import LoginButton from '../components/LoginButton';

export default function Login(){ // props 넘겨주지 않고
	return (
		<div>
			<h2>Login 페이지 입니다.</h2>
			<LoginButton /> // props 넘겨주지 않고
		</div>
	);
}

2) src/components/LoginButton.jsx 를 가져다 쓰는데

import { withRouter } from 'react-router-dom' // react-router-dom에 있는 withRouter 추가

export default withRouter( function LoginButton() {
	console.log(props);

	function login() {
		setTimeout( () => {
			props.history.push('/')
		}, 1000);
	}

	return <button onClick={login}>로그인하기</button>
});

해결방법 2 : Hooks 사용

뒤의 챕터에서 배울 예정

7. Redirect

<Redirect /> 컴포넌트

곧바로 to에 설정한 경로로 이동됨

import { Redirect } from 'react-router-dom'length

// jsx
<Redirect to="/" />

src/App.js

import { BrowserRouter, Route, Switch, Links } from 'react-router-dom';
import Home from './pages/Home';
import Profile from './pages/Profile';
import About from './pages/About';
import NotFound from './pages/NotFound';
import Links from './components/Links';
import NavLinks from './components/NavLinks';
import Login from './pages/Login';

const isLogin = true; // isLogin이 참이면 Rediect를 가져와서 바로 홈으로 이동

function App() {
	return (
		<BrowserRouter>
		<Links />
		<NavLinks />
		<Switch>
			<Route path="/login"
				render={ () => isLogin ? <Redirect to="/" /> : <Login />
			} />
			<Route path="/profile/:id" component={Profile}  />
			<Route path="/profile" component={Profile}  />
			<Route path="/about" component={About} />
			<Route path="/" exact component={Home} />
			<Route component={NotFound} />
		</Switch>
		</BrowserRouter>
	);
}

export default App;

추가 학습자료

정리하기

  • 웹 애플리케이션에서의 페이지 이동 이해
    웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것을 의미함. 만들 때 프로젝트를 하나의 페이지로 구성할 수도 있고, 여러 페이지를 구성할 수도 있음.
  • 라우팅이란 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것
  • 리액트는 SPA (Single Page Application) 방식으로 기존 웹 페이지 처럼(MPA 방식) 여러개의 페이지를 사용, 새로운 페이지를 로드하는 방식이 아님.
  • 새로운 페이지를 로드하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가짐
  • React-Router
    신규 페이지를 불러오지 않는 상황에서 각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링해주는 라이브러리. 사용자가 입력한 주소를 감지하는 역할을 하며, 여러 환경에서 동작할 수 있도록 여러 종유의 라우터 컴포넌트를 제공. (컴포넌트 기반으로 라우팅 시스템을 설정)
  • URL 파라미터쿼리 스트링
    파라미터, 쿼리스트링을 통해 유동적으로 동작할 수 있음.

현재..
1) 그냥 듣기
2) 강의보며 클론코딩
3) 강의보며 정리
4) 이해 안가는 거 구글링 서칭 (필수인듯)
이런 식으로 3-4번 돌려서 공부중인데,
(ebs 수능 특강도 이렇게 안 들어봤는데..🥲)

그래도 강의가 짧아서 좋은 거 같다.
다만 기본개념보다 복잡하게 응용하려면 거기서 막힐 듯..
어렵지만 열심히 😠🙂

profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글