


React는 작성, 렌더, 업데이트에 관여하는데,
route는 기본적으로 react의 범주를 넘어서는 작업
⇒React Router DomLibrary가 그 일을 대신함
$npm i react-router-dom
CRA에 기본 내장된 패키지도, 공식 패키지도 아님
가장 대표적인 라우팅 패키지임
// App.js
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './pages/Home'
import Profile from './pages/Profile'
import About from './pages/About'
import './App.css'
function App() {
  return (
    <BrowserRouter>
      <Route path="/" exact component={Home}></Route>
      <Route path="/profile" component={Profile}></Route>
      <Route path="/about" component={About}></Route>
    </BrowserRouter>
  )
}
export default App
export default function Profile() {
  return (
    <div>
      <h2>Profile</h2>
    </div>
  )
}
params: 필수 요소http://localhost:3000/profile/10// App.js
(...)
<Route path="/profile" exact component={Profile}></Route>
<Route path="/profile/:id" component={Profile}></Route>
(...)
// profile.jsx
export default function Profile(props) {
  const id = props.match.params.id
  console.log(id, typeof id)
  return (
    <div>
      <h2>Profile</h2>
      {id && <p>id 는 {id} 입니다.</p>}
    </div>
  )
}
query string: 선택적 요소http://localhost:3000/about?name=hellexport default function About(props) {
  const searchParams = props.location.search
  console.log(searchParams)
  const obj = new URLSearchParams(searchParams)
  const name = obj.get('name')
  console.log(name)
  return (
    <div>
      <h2>About</h2>
      {name && <p>name은 {name}입니다.</p>}
    </div>
  )
}
import queryString from 'query-string'
export default function About(props) {
  const searchParams = props.location.search
  console.log(searchParams)
  // const obj = new URLSearchParams(searchParams)
  // const name = obj.get('name')
  // console.log(name)
  const query = queryString.parse(searchParams)
  console.log(query)
  return (
    <div>
      <h2>About</h2>
      {query.name && <p>name은 {query.name}입니다.</p>}
    </div>
  )
}
exact를 뺄 수 있게 해줌path에도 맞지 않는 경우를 설정해서 Not Found 페이지를 만들 수 있음// App.js
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './pages/Home'
import Profile from './pages/Profile'
import About from './pages/About'
import NotFound from './pages/NotFound.jsx'
import './App.css'
function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/profile/:id" component={Profile}></Route>
        <Route path="/profile" component={Profile}></Route>
        <Route path="/about" component={About}></Route>
        <Route path="/" exact component={Home}></Route>
        <Route component={NotFound}></Route>
      </Switch>
    </BrowserRouter>
  )
}
export default App
<a></a>태그를 통해 이동하면 React Application의 SPA 특성을 담은 페이지 이동이 아니라 서버에 새로운 요청을 일으킴. 즉, 새로고침이 일어남
⇒<Link></Link>컴포넌트를 활용
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom' // Link import
import Home from './pages/Home'
import Profile from './pages/Profile'
import About from './pages/About'
import NotFound from './pages/NotFound.jsx'
import './App.css'
function App() {
  return (
    <BrowserRouter>
      <Link to="/">Home</Link>
      <Switch>
        <Route path="/profile/:id" component={Profile}></Route>
        <Route path="/profile" component={Profile}></Route>
        <Route path="/about" component={About}></Route>
        <Route path="/" exact component={Home}></Route>
        <Route component={NotFound}></Route>
      </Switch>
    </BrowserRouter>
  )
}
export default App
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=hell">About?name="hell</Link>
      </li>
    </ul>
  )
}
import {NavLink} from 'react-router-dom'// NavLinks.js
import { NavLink } from 'react-router-dom'
const activeStyle = { color: 'green' }
export default function NavLinks() {
  return (
    <ul>
      <li>
        <NavLink to="/" exact activeStyle={activeStyle}>
          Home
        </NavLink>
      </li>
      <li>
        <NavLink to="/profile" exact activeStyle={activeStyle}>
          Profile
        </NavLink>
      </li>
      <li>
        <NavLink to="/profile/1" activeStyle={activeStyle}>
          Profile/1
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/about"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            console.log('match', match)
            console.log('location', location)
            return match !== null && location.search === ''
          }}
        >
          About
        </NavLink>
      </li>
      <li>
        <NavLink
          to="/about?name=hell"
          activeStyle={activeStyle}
          isActive={(match, location) => {
            console.log('location', location)
            return match !== null && location.search === '?name=hell'
          }}
        >
          About?name=hell
        </NavLink>
      </li>
    </ul>
  )
}
// Login.jsx
export default function Login(props) {
  console.log('props', props)
  function login() {
    setTimeout(() => {
      props.history.push('/') // go, goback, push, replace...
    }, 1000)
  }
  return (
    <div>
      <h2>Login</h2>
      <button onClick={login}>로그인하기</button>
    </div>
  )
}
// Login.jsx
import LoginButton from '../components/LoginButton'
export default function Login(props) {
  return (
    <div>
      <h2>Login</h2>
      <LoginButton {...props} />
    </div>
  )
}
// LoginButton.jsx
export default function LoginButton(props) {
  console.log('LoginButton Props', props)
  function login() {
    setTimeout(() => {
      props.history.push('/')
    }, 1000)
  }
  return <button onClick={login}>로그인하기</button>
}
Higher Order Component인 withRouter 활용// Login.jsx
import LoginButton from '../components/LoginButton'
export default function Login() {
  return (
    <div>
      <h2>Login</h2>
      <LoginButton />
    </div>
  )
}
// LoginButton.jsx
import { withRouter } from 'react-router-dom'
export default withRouter(function LoginButton(props) {
  console.log('LoginButton Props', props)
  function login() {
    setTimeout(() => {
      props.history.push('/')
    }, 1000)
  }
  return <button onClick={login}>로그인하기</button>
})
import { Redirect} from 'react-router-dom
// App.js
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'
// import Links from './components/Links.jsx'
import NavLinks from './components/NavLinks.jsx'
import Login from './pages/Login'
import Home from './pages/Home'
import Profile from './pages/Profile'
import About from './pages/About'
import NotFound from './pages/NotFound.jsx'
import './App.css'
const isLogin = false // isLogin에 따라서 home으로 갈지 login으로 갈지 결정됨
function App() {
  return (
    <BrowserRouter>
      {/* <Link to="/">Home</Link> */}
      {/* <Links></Links> */}
      <NavLinks></NavLinks>
      <Switch>
        <Route
          path="/login"
          render={() => (isLogin ? <Redirect to="/" /> : <Login />)}
        ></Route>
        <Route path="/profile/:id" component={Profile}></Route>
        <Route path="/profile" component={Profile}></Route>
        <Route path="/about" component={About}></Route>
        <Route path="/" exact component={Home}></Route>
        <Route component={NotFound}></Route>
      </Switch>
    </BrowserRouter>
  )
}
export default App