React 시험 D-day 1 #29

CoderS·2022년 1월 25일
0

리액트 Remind

목록 보기
29/32

#29 유연한 사고를 갖자!

서브라우트

  • 서브라우트, 즉 라우트 내부의 라어트를 만드는 것을 의미한다.

이 작업은 복잡하지 않아서 그냥 컴포넌트를 만들어서 그 안에 또 Route 컴포넌트를 렌더링하면 된다.

※ 서브 라우트 만들어보기

우선 src 에 Profiles 라는 컴포넌트를 만들어서, 그 안에 각 유저들의 프로필 링크들과 프로필 라우트를 함께 렌더링해겠다.

Profiles.js

import React from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import Profile from './Profile';

const Profiles = () => {
  return (
    <div>
      <h3>유저 목록:</h3>
      <ul>
        <li>
          <Link to="/profiles/velopert">velopert</Link>
        </li>
        <li>
          <Link to="/profiles/gildong">gildong</Link>
        </li>
      </ul>
        <Routes>
            <Route path="/profiles" element={<div>유저를 선택해주세요.</div>}/>
            <Route path="/profiles/:username" element={<Profile />} />
        </Routes>
    </div>
  );
};

export default Profiles;

위 코드에서는 첫 번째 Route 컴포넌트에서 element 대신에 render 가 사용되었다.

여기서 컴포넌트가 아니라 JSX 자체를 렌더링 할 수 있다. JSX 를 렌더링하는 것이기에, 상위 영역에서 props 나 기타 값들을 필요하면 전달 해 줄 수 있다.

다음으로 App 에서 Profiles 를 위한 링크와 라우트를 생성해준다. (기존 Profiles 라우트는 제거해준다.)

App.js

import React from 'react';
import { Route, Link, Routes } from 'react-router-dom';
import About from './About';
import Home from './Home';
import Profiles from './Profiles';

const App = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">소개</Link>
        </li>
        <li>
          <Link to="/profiles">프로필 목록</Link>
        </li>
      </ul>
      <hr />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<Profiles />} />
      </Routes>
    </div>
  );
};

export default App;

velopert 를 클릭했을 때...

gildong 를 클릭했을 때...

잘 출력이되는걸 확인 할 수 있다.

리액트 라우터 부가기능

이번에는 알아두면 유용한 리액트 라우터의 부가기능들을 알아보겠다.

※ useNavigate

history 객체는 라우트로 사용된 컴포넌트에게 match, location 과 함께 전달되는 props 중 하나이다. 이 객체를 통해서 우리가 컴포넌트 내에 구현하는 메소드에서 라우터에 직접 접근을 할 수 있다.

예 ) 뒤로가기, 특정 경로로 이동, 이탈 방지 등..

그런데 이 객체가 새로운 리액트 라우터에서는 사라져서 useNavigate 훅을 사용해야 한다.

useNavigate 은 useHistory의 기능을 전부 대체 가능하다
그리고 useHistory의 history는 객체였지만 useNavigate의 navigate는 함수다.

예 )

const navigate = useNavigate();

navigate('/');
navigate(-1);
navigate(-2);
navigate(`/user/${user._id}`);

src 디렉토리에 HistorySample.js 파일을 만들어주고 다음과 같이 코드를 작성해준다.

HistorySample.js

import React, { useEffect } from 'react';
import {useNavigate} from 'react-router-dom'

function HistorySample() {
  const navigate = useNavigate();
  const goBack = () => {
    if(!window.confirm("정말로 떠나실건가요?")){
      navigate(0);
    }else{
      navigate(-1);
    }
  };

  const goHome = () => {
    if(window.confirm("정말로 떠나실건가요?")){
      navigate('/');
    }else{
      navigate(0);
    }
  };

  useEffect(() => {
    
  }, []);

  return (
    <div>
      <button onClick={goBack}>뒤로가기</button>
      <button onClick={goHome}>홈으로</button>
    </div>
  );
}

export default HistorySample;

그리고 App 에서 렌더링하고 버튼을 눌러보면...

App.js

import React from 'react';
import { Route, Link, Routes } from 'react-router-dom';
import About from './About';
import Home from './Home';
import Profiles from './Profiles';
import HistorySample from './HistorySample';

const App = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">소개</Link>
        </li>
        <li>
          <Link to="/profiles">프로필 목록</Link>
        </li>
        <li>
          <Link to="/history">예제</Link>
        </li>
      </ul>
      <hr />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<Profiles />} />
        <Route path="/history" element={<HistorySample />} />
      </Routes>
    </div>
  );
};

export default App;

useNavigate 을 사용해서 다른 곳으로 이동도 가능하고, 이탈시 메시지박스를 통하여 막을 수 도 있다.

※ useLocation 과 useParams

사실 withRouter 를 사용해서 match / location / history 객체를 불러올려고 했는데 하필 리액트 라우터 버전이 6으로 바뀌면서 사라져버렸다.

그리하여 할 수 없이 useLocation 과 useParams 를 사용해서 textarea 태그에 정보들을 집어넣겠다.

useLocation

  • 참고로 useLocation 은 사용자가 현재 머물러있는 페이지에 대한 정보를 알려주는 hooks 이다.

useParams

  • 그리고 useParams 은 useLocation 과 매우 유사한 hooks 이지만 path parameter의 정보를 얻을 수 있는 hooks 로 사용된다.

src 에 WithRouterSample.js 파일을 만들어주고 밑에 코드를 참고해라!

WithRouterSample.js

import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';

const WithRouterSample = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const params = useParams();
  console.log(params) 
  return (
    <div>
      <h4>location</h4>
      <textarea value={JSON.stringify(location, null, 2)} readOnly />
      <h4>match</h4>
      <textarea value={JSON.stringify(params, null, 2)} readOnly />
      <button style={{display:"block"}} onClick={() => {navigate('/')}}>홈으로</button>
    </div>
  );
};

export default WithRouterSample;

그리고 이것을 Profiles.js 에 렌더링해준다.

Profiles.js

import React from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import Profile from './Profile';
import WithRouterSample from './WithRouterSample';

const Profiles = () => {
  return (
    <div>
      <h3>유저 목록:</h3>
      <ul>
        <li>
          <Link to="/profiles/velopert">velopert</Link>
        </li>
        <li>
          <Link to="/profiles/gildong">gildong</Link>
        </li>
      </ul>
        <Routes>
            <Route path="/profiles" element={<div>유저를 선택해주세요.</div>}/>
            <Route path="/profiles/:username" element={<Profile />} />
        </Routes>
        <Routes>
          <Route path="/profiles/:username" element={<WithRouterSample />} />
        </Routes>
    </div>
  );
};

export default Profiles;

velopert 를 클릭했을 때 이렇게 각 정보들을 확인할 수 있다.

NavLink 는 Link 랑 비슷한데, 만약 현재 경로와 Link 에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 클래스를 적용 할 수 있는 컴포넌트이다.

그러면 한번 Profiles 애서 사용하는 컴포넌트에서 Link 대신 NavLink 를 사용해보겠다.

Profiles.js

import React from 'react';
import { Link, Route, Routes, NavLink } from 'react-router-dom';
import Profile from './Profile';
import WithRouterSample from './WithRouterSample';

const Profiles = () => {
  return (
    <div>
      <h3>유저 목록:</h3>
      <ul>
        <li>
          <NavLink to="/profiles/velopert" style={({ isActive }) => ({ color: isActive ? 'white' : 'rgb(85, 26, 139)', background: isActive ? 'black' : null })}>velopert</NavLink>
        </li>
        <li>
          <NavLink to="/profiles/gildong" style={({ isActive }) => ({ color: isActive ? 'white' : 'rgb(85, 26, 139)', background: isActive ? 'black' : null })}>gildong</NavLink>
        </li>
      </ul>
        <Routes>
            <Route path="/profiles" element={<div>유저를 선택해주세요.</div>}/>
            <Route path="/profiles/:username" element={<Profile />} />
        </Routes>
        <Routes>
          <Route path="/profiles/:username" element={<WithRouterSample />} />
        </Routes>
    </div>
  );
};

export default Profiles;

기존에 있던 activeStyle 대신 activeClassName 가 사라지면서 다음과 같이 삼항 조건 연산자 를 사용해서 클릭하면 글자에 검정색 배경과 하얀색 폰트로 바뀐다.

벨로퍼트에 있는 코드들은 버전 6 전이여서 아무리 구현해봐도 되지를 않는다.

무엇이 바뀌었는지 궁금하면 알아서 잘 찾아보자!

참고 : 벨로퍼트와 함께하는 모던 리액트

느낀점 :

  • 내가 벨로퍼트를 공부하면서 이렇게 막힌 부분이 있는지 처음 알았다.
  • 현재 리액트 라우터가 새로운 버전으로 바뀌면서 많이 사라진 것들이 많다. 그리하여 잘 찾아봐서 이용해야겠다.
profile
하루를 의미있게 살자!

0개의 댓글