5월 25일(Router)

JY·2022년 5월 25일
0
post-thumbnail

SPA(Single Page Application)


새 페이지를 보여줄 때, 페이지 이동 대신 자바스크립트를 이용하여 기존 DOM을 새로운 DOM으로 대체한다.

MPA와 비교했을 때 SPA의 장단점

  • 장점: 자연스러운 페이지 이동 UX 제공 가능
    • 새로고침이 발생하지 않는다.
    • 모바일 앱처럼 애니메이션을 적용할 수 있다.
  • 단점: 추가 공수가 필요하다.
    • 렌더될 DOM을 교체하는 작업이 필요하다.

SSR vs CSR과는 다른 개념이다. 장단점을 혼동하지 않도록 주의해야 한다.

1. React Router


리액트 프로젝트에서 SPA를 쉽게 도입할 수 있도록 도와주는 라이브러리이다.

npm i react-router-dom

  • <BrowserRouter>: react-router를 사용할 앱에서 단 한 번만 사용한다.
  • <Routes>: <Route>를 아래와 같이 동작하도록 만든다.
  • <Route>: props.path와 브라우저의 url이 일치하면 props.element를 return한다. 가장 먼저 일치하는 Route만 적용한다.
  • <Link>: props.to에 적힌 url로 http get request를 보내지 않고 브라우저에 표시되는 url만 변경한다. 실제 페이지 이동은 하지 않는다.

element={<Main />} === 리액트 엘리먼트
👉 컴포넌트를 JSX 형태로 렌더시킨 것이다.

<a href=""> 대신 <Link>를 사용
anchor 태그는 브라우저 url을 '이동'

일반적으로 index.js에서 사용한다.

import { BrowserRouter, Routes, Route, Link, useParams } from "react-router-dom";
import Form from './Form';

...

const Hello = () => {
  const params = useParams();
  console.log(params);
  return (
    <Link to='/'>to home</Link>
  )
}

const Main = () => (
  <Link to='/hello/5'>to hello with id 5</Link>
)

root.render(
    <div>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Main />} />
          <Route path="/hello/:id" element={<Hello />} />
          <Route path="/form" element={<Form />} />
        </Routes>
      </BrowserRouter>
    </div>
);

reportWebVitals();

바뀌지 않는 header와 footer 같은 경우 다음처럼 사용할 수 있다.

2. parameter



  • useParams()
    • 공식적인 리액트 hooks는 아니다.
    • 커스텀 훅이다.
    • url에 있는 특정 값을 받아올 수 있다.


3. 실습



// index.js

import { BrowserRouter, Routes, Route, Link, useParams, useNavigate } from "react-router-dom";
import Form from './Form';

const Mypage = () => {
  const params = useParams();
  let navigate = useNavigate();
  console.log(params);

  return (
    <div>
      안녕하세요 {params.id}!
      <br/>
      <button onClick={() => {
        navigate('/');
      }}>로그아웃</button>
    </div>
  )
}

root.render(
  // <React.StrictMode>
    // <App />
    <div>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Form />} />
          <Route path="/mypage/:id" element={<Mypage />} />
        </Routes>
      </BrowserRouter>
    </div>
  //  {/* <TestComponent /> */}
  // </React.StrictMode>
  
);
// Form.js

import React, {useState, useRef} from 'react'
import { Link } from "react-router-dom";

export default function Form() {
  const [id, setId] = useState("");
  const [password, setPassword] = useState("");
  const idRef = useRef(null);
  const passwordRef = useRef(null);
  const idMsg = "유효하지 않은 id입니다.";
  const passwordMsg = "유효하지 않은 password입니다.";
  const idCheck = (id.length >= 6 && id.length <= 20);
  const passwordCheck = (password.length >= 12 && password.length <= 20);
  // let navigate = useNavigate();

  const handleChangeInput = (e) => {
    if(e.target.name === "id") {
      setId(e.target.value);
    }
    if(e.target.name === "password") {
      setPassword(e.target.value);
    }
  }

  const handleClick = (e) => {
    if ( !idCheck ) {
      alert(idMsg);
      setId('');
      idRef.current.focus();
      e.preventDefault();
    }
    else if ( !passwordCheck ) {
      alert(passwordMsg);
      setPassword('');
      passwordRef.current.focus();
      e.preventDefault();
    }
  };

  return (
  <div>
    <div>
      <input type="text" name='id' ref={idRef} value={id} onChange={handleChangeInput} placeholder='6글자 이상 20글자 이하' />
      {id ? 
        idCheck ? null : idMsg
      : null}
    </div>
    <div>
      <input type="text" name='password' ref={passwordRef} value={password} onChange={handleChangeInput} placeholder='12글자 이상 20글자 이하' />
      {password ? 
        passwordCheck ? null : passwordMsg
      : null}
    </div>
    
    <Link to={`/mypage/${id}`}  >
        <button onClick={handleClick} disabled={
      (id || password) ? false : true 
      }>로그인</button>
    </Link>
  </div>
  );
}





참고

profile
🙋‍♀️

0개의 댓글