React Router

스카치·2023년 2월 15일
0

React의 라우팅 이해하기!

전통적인 브라우저 : 필요할 때마다 서버에 요청해서 데이터를 받아옴

SPA(Single page application) : 하나의 큰 앱을 받아 온 후 브라우저(client)에서 보여줄 것들을 취사선택

리액트 라우터 돔(React router dom) = 브라우저에서 어떤 컴포넌트를 보여줄지에 대한 로직을 처리
npm i react-router-dom

npx create-react-app react-router-example
-> cd react-router-example
-> npm i react-router-dom // 리액트 라우터 설치
-> code . -r

src폴더 안에서
pages폴더 생성 -> Home.jsx , Profile.jsx , About.jsx 파일 생성
Home.jsx ->

export default function Home() {
	return	<div>Home페이지 입니다.</div>

Profile.jsx ->

export default function Profile() {
	return	<div>Profile페이지 입니다.</div>

About.jsx ->

export default function About() {
	return	<div>About페이지 입니다.</div>

App.js ->
App 함수 내용 전부 지우기

import {BrowserRouter, Route} from 'react-router-dom';

function App() {
  return (
      <BrowserRotuer>  // react-router-dom에서 가져옴 (= import {BrowserRouter} from 'react-router-dom'; 
        <Route path="/" element={<Home />} // Route = 라우터 돔, path= 경로, element = 보여줄 컴포넌트
        <Route path="/Profile" element={<Home />}  
        <Route path="/About" element={<About />}
        <Route path="/Profile/About" element={<Profile />}>    
      // 다 컴포넌트가 중복되어 나옴 ->
      /*
		- <Route path="/" exact element={Home} //  v6에서 exact삭제
		
        - exact 는 더이상 사용하지 않고 여러 라우팅을 매칭하고 싶은 경우 URL 뒤에 * 을 사용합니다.
			ex) <Route path="/page1/*" element={<Page1 />} />
		- component 방식 변경 (component={COM} 및 render={() => <h1>Hello<h1/>} 삭제)
		- path 를 기존의 path="/Web/:id" 에서 path=":id" 로, 상대경로로 지정
		- 이 외에도, path="." / path=".." 등으로 상대경로를 표현한다
*/
       </BrowserRotuer>
  )
}

Dynamic라우팅(1)

Dynamic라우팅 : 컴포넌트의 경로가 동적일 때 사용
App.js ->

return (
	<BrowserRotuer> 
      <Route path="/" exact component={Home}   
      <Route path="/Profile" exact component={Profile}
      //----//
      // /profile/1 의 경로를 가진 컴포넌트를 가지고 싶다면
      <Route path="/Profile/:id" component={Profile} // :[이름]을 통해 컴포넌트에서 데이터를 받아 사용가능
      //-----//
      <Route path="/About" component={About}
>   </BrowserRotuer>
)

Profile.js ->

export default function Profile(props) { // 컴포넌트에 데이터가 들어온다면 props를 통해 들어옴
	console.log(props)
 	return <div>Profile페이지 입니다.</div>
}

props =

= id값은 props.match.params.id 를 통해 접근가능
Profile.js ->

export default function Profile(props) {
	console.log(props)
  	const id = props.match.params.id
    console.log(id, typeof id) // id의 타입은 string
 	return (
      <div>
        <h2>Profile페이지 입니다.</h2>
        {id && <p>는 id는 {id}입니다.</p>}
      </div>
    )
}

==

정리

Dynamic라우팅(2)


localhost:3000/about?name=mark에서
경로에 about?name=mark 와 같은 querystring은 about과 같아서 추가적으로 라우팅할 필요가 없다.(=옵션)

name=mark를 꺼내오고 싶다면

props.location.search으로 name=mark에 접근가능

about.jsx =>

export default function About(props) {
	console.log(props)
 	return <div>About페이지 입니다.</div>
}

특정 params의 데이터를 가져오는 방법

방법 1. 브라우저 내장 객체 사용 (URLSearchParams 함수)

about.jsx =>

export default function About(props) {
	console.log(props)
  	const searchParams = props.location.search;
  	console.log(searchParams)
  	const obj = new URLSearchParams(searchParams)
  	console.log(obj.get('name')) // >> 'mark'
  		// 단점 1. RLSearchParams의 메서드를 외워야함
  	 	// 2. URLSearchParams지원 안하는 브라우저가 있음(Internet Explorer)
  	
  return <div>About페이지 입니다.</div>
}

방법 2. query-string 패키지 사용

	//  npm i query-string -S

about.jsx =>

import queryString from 'query-string'

export default function About(props) {
	console.log(props)
  	const searchParams = props.location.search;
  	console.log(searchParams)
  	const query = queryString.parse(searchParams)
    console.log(query) // >> {name:"mark"} 라는 객체로 반환
  return (
    <div>
      <h2>About페이지 입니다.</h2>
      {query.name && <p>name 은 {query.name}입니다.</p>}
    </div>
  )
}

return (
	<BrowserRotuer> 
    <Route path="/" exact component={Home}   
    <Route path="/Profile" exact component={Profile}
    //----//
    <Route path="/Profile/:id" component={Profile}  
	//-----//
    <Route path="/About" component={About}
>   </BrowserRotuer>
)

Routes와 NotFount

Switch 컴포넌트 ==> Routes로 변경(v6~)

App.jsx =>

return (
	<BrowserRotuer>
  	<Switch> // 컴포넌트를 돌며 가장 적합한 컴포넌트를 보여줌. 
      // 가장 좁거나 하위 컴포넌트부터 돌아야 적합한 결과를 얻을 수 있음
      <Route path="/Profile/:id" component={Profile}>  
      <Route path="/Profile" component={Profile}>
      <Route path="/About" component={About}>
      <Route path="/" exact component={Home}> 
        // switch를 쓰면 exact는 가장 마지막 컴포넌트에만 붙이면됨
        
      // 다 돌아도 찾을 수 없으면 Not found 컴포넌트를 보여줌
      <Route component={NotFound}> // NotFound 컴포넌트는 경로를 지정안해도됨
    </Switch>
    </BrowserRotuer>
)

src => pages => NotFound.jsx 생성
NotFound.jsx =>

export default function NotFound() {
	return <div>페이지를 찾을 수 없습니다</div>
}

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

react application 내부에서 페이지를 이동할 때 a태그 사용시 리액트에서 문제 생김 => 새로 서버에서 받아옴
react-router-dom 의 Link 컴포넌트를 통해 서버를 통하지 않고 링크를 변경할 수 있음

App.jsx =>

return (
	<BrowserRotuer>
    
    <Link to="/">Home<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}> // NotFound 컴포넌트는 경로를 지정안해도됨
    </Switch>
    </BrowserRotuer>
)

Link가 모여있는 컴포넌트 만들어서 경로 이동하기

src => components 폴더 생성 => Links.jsx 생성
Links.jsx =>

import {Link} from 'react-router-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>
    )
}

App.jsx =>

return (
	<BrowserRotuer>
    <Links />    // -----------//
  	<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}> // NotFound 컴포넌트는 경로를 지정안해도됨
    </Switch>
    </BrowserRotuer>
)

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

navigation link :

  • active의 기능을 가지고 있는 navigation link
  • 해당 링크로 이동했을 때 특정 기능을 active할 수 있다.

src => NavLinks.jsx 생성
NavLinks.jsx =>

import {NavLinks} from 'react-router-dom'

const activeStyle = {color:'green'};

export default function Links() {
	return (
    	<ul>
        	<li>
            	<NavLinks to="/" exact activeStyle={activeStyle}>Home</NavLinks>
            </li>
            <li>
            	<NavLinks to="/profile" exact activeStyle={activeStyle}>Profile</NavLinks>
            </li>
            <li>
            	<NavLinks to="/profile/1" activeStyle={activeStyle}>Profile/1</NavLinks>
            </li>
            <li>  // /about 경로는 ?name=mark경로와 겹치기 때문에 exact 만으로 독립성을 유지할 수 없다. isActive 함수 사용(true일 때만 적용)
            	<NavLinks 
                  to="/about"   
                  activeStyle={activeStyle}
                  isActive={(match, location) => {
                	console.log(match, location);
                  	return match !== null && location.search === "";
                	}}
                  >About</NavLinks>
            </li>
            <li>
            	<NavLinks 
                  to="/about?name=mark" 
                  activeStyle={activeStyle}
				  isActive={(match, location) => {
                	console.log(match, location);
                  	return match !== null && location.search === "?name=mark";
                	}}                  
				 >About?name=mark</NavLinks>
            </li>
        </ul>
    )
}

JS로 라우팅 이동하기

App.jsx =>

return (
	<BrowserRotuer>
    <Links />    // -----------//
  	<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}> // NotFound 컴포넌트는 경로를 지정안해도됨
    </Switch>
    </BrowserRotuer>
)

page => Login.jsx 생성

export default function Login(props) {
  console.log(props)
  function login() {
  	setTimeout( () => {
    	//페이지를 이동
      props.history.push('/');
    }, 1000)
  }
  
	return (
    	<div>
        <h2> Login 페이지 입니다. </h2>
        <button onClick= {login}로그인하기</button>
        </div>
    )
}          
         

그러나 구조가 복잡해질수록 하위 컴포넌트에서 props를 받기 힘들어질 수 있다.

구조가 복잡해졌을 때 props를 상속 받는법

방법 1 hoc(higher order component) 사용

components => LoginButton.jsx 생성=>

import {withRouter} from 'react-router-dom'
// withRouter = hoc
// 작성한 컴포넌트를 withRouter의 인자로 넣고 실행된 결과물을 컴포넌트로 사용한다
export default withRouter( function LoginButton(props) {
	console.log(props);
  	function login() {
      setTimeout( () => {
        props.history.push('/');
      },1000)	
    }
    return <button onClick={login}> 로그인하기 </button>
  
  })

page => Login.jsx

import LoginButton from '../components/LoginButton'

export default function Login() {
  return (
    <div>
      <h2>Login 페이지 입니다.</h2>
      <LoginButton /> 
      // props를 받지 않았으므로 로그인버튼을 눌렀을 때 이동할 경로를 설정하지 못함. Login 함수의 매개변수로 props를 상속받아 쓸 수도 있지만 구조가 심층화될수록 복잡해짐. ==> hoc사용
    </div>
  )
}

방법 2 hook사용

Redirect


조건이 충족되면 다른 경로로 redirect 시키는 컴포넌트

const isLogin = true;
<Route 
  path='/login'
  render={ () => (isLogin ? <Redirect to='/' /> : <Login />) }
// render = 함수사용
// isLogin이 true이면 Redirect 경로로 이동, 아니면 Login 경로로 이동

0개의 댓글