TIL | #17 React | react-router-dom

trevor1107·2021년 4월 11일
0

2021-04-07(수)

React Router DOM module

yarn add react-router-dom

Route 컴포넌트

어떤 규칙을 가진 경로에 어떠한 컴포넌트를 보여줄지 정의할 수 있다.

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

라우트 컴포넌트를 이용해서 라우트를 설정해준다.

<Route path="주소규칙(/login 등)" component={보여줄 컴포넌트}></Route>

// App.js

import { Route } from 'react-router-dom'
import About from './About';
import Home from './Home';

<Route path="/" component={Home}/>
<Route path="/about" component={About} />

// 이 상태로는 /about 라우트에 접근하면 Home과 About 모두 포함되어 화면에 그려진다.
// props exact=true를 설정한다.
<Route path="/" component={Home} exact={true} />

// 다중 라우트 설정하는 방법, path를 다음과 같이 설정하면 된다.
<Route path={['/about', '/info']} component={About} />

Route라고 입력하면 자동완성으로 react-router가 기본적으로 import로 추가된다.

여기서 한가지 주의할 점은 react-router-dom 모듈과 react-router은 버전 차이가 있다.

차이점은 https://blueshw.github.io/2017/06/22/static-routing-vs-dynamic-routing/ 링크를 참고.

a태그 처럼 다른 링크로 이동하는 기능을 제공하는 컴포넌트이다.

페이지를 새로 불러오지 않고 애플리케이션은 그대로 유지하고 history API를 사용해서 페이지의 주소만 변경한다.

<Link to="주소">내용</Link>

// App.js

...

<li>
    <Link to="/">Home</Link>
</li>
<li>
    <Link to="/about">About</Link>
</li>

<Route path="/" component={Home} exact={true} />
<Route path={['/about', '/info']} component={About} />

URL Params

// App.js

...

<li>
    <Link to="/profile/kyungil">kyungil 프로필</Link>
</li>
<li>
    <Link to="/profile/academy">academy 프로필</Link>
</li>

{/* match.params.username값을 통해 현재 username 조회 */}
<Route path="/profile/:username" component={Profile} />
// Profile.js

import React from 'react';

const data = {
    kyungil: {
        name: '놀부',
        description: '욕심쟁이',
    },
    academy: {
        name: '홍길동',
        description: '동해번쩍 서해번쩍',
    },
};

// URL 매개변수를 사용할 때는 라우트로 사용되는 컴포넌트에서
// 받아오는 match라는 객체안에 params 값을 참조한다.
// match안에는 현재 컴포넌트가 어떤 경로 규칙에 의해
// 보이는지에 대한 정보가 들어있다.
const Profile = ({ match }) => {
    const { username } = match.params;
    const profile = data[username];
    if (!profile) {
        return <div>사용자 없음</div>;
    }
    return (
        <div>
            <h3>
                {username}({profile.name})
            </h3>
            <p>{profile.description}</p>
        </div>
    );
};

export default Profile;

http://localhost:3000/about?detail=true 링크로 결과를 확인한다.

URL Query

쿼리는 location 객체에 들어있는 search 값에서 조회할 수 있다.
location객체는 라우트로 사용된 컴포넌트에게 props로 전달되고 웹 애플리케이션의 현재 주소에 대한 정보를 가지고 있다.

쿼리 스트링 모듈 설치 yarn add qs

// http://localhost:3000/about?detail=true
{
    "pathname" : "/about",
    "search" : "detail=true",
    "hash" : ""
}
// About.js

import qs from 'qs';

function About({ location }) {
    const query = qs.parse(location.search, {
        ignoreQueryPrefix: true, // 문자열 맨 앞에 '?' 생략
    });

    // 쿼리 파싱의 결과는 문자열이다.
    const showDetail = query.detail === 'true';

    return (
        <div>
            <h1>어바웃 페이지</h1>
            <p>여기는 어바웃 페이지 입니다.</p>
            {showDetail && <p>디테일 값은 true</p>}
        </div>
    );
}

export default About;

쿼리를 쓸 때 쿼리 문자열을 객체로 파싱하는 과정에서의 결과 값은 언제나 문자열이다.
?value=1 -> ("1"), ?value=true -> ("true")

숫자를 받아와야 하는 상황에서는 parseInt 함수를 사용하고
논리 값을 사용하는 경우는 정확히 true라는 문자열이랑 일치하는지 비교한다.

http://localhost:3000/about?detail=true 주소로 들어가게되면 URL 쿼리의 결과를 확인할 수 있다.

History (props)

라우트로 사용된 컴포넌트에 match, location과 함께 전달되는 props중 하나이다. history를 통해 컴포넌트 내에 구현하는 메서드에서 라우터 API를 호출할 수 있다.
예) 버튼 클릭 -> 뒤로 가기, 다른 페이지 이탈방지, 로그인 후 화면전환 ...

// HistorySample.js

import React, { Component } from 'react';

export class HistorySample extends Component {
    handleGoBack = () => {
        this.props.history.goBack();
    };
    handleGoHome = () => {
        this.props.history.push('/');
    };
    componentDidMount() {
        // 페이지에 변화가 생기려고 할 때 마다 고고씽?
        this.unblock = this.props.history.block('고고씽?');
    }
    componentWillUnmount() {
        // 컴포넌트가 언마운트되면 고고씽?을 멈춘다.
        if (this.unblock) this.unblock();
    }
    render() {
        return (
            <div>
                <button onClick={this.handleGoBack}>뒤로가기</button>
                <button onClick={this.handleGoHome}>홈으로</button>
            </div>
        );
    }
}

export default HistorySample;

WithRouter 함수

라우트로 사용된 컴포넌트가 아니어도 location, history, match 객체에 접근할 수 있게 해준다.

import { WithRouter } from 'react-router-dom';

// WithRouterSample.js

import React from 'react';
import { withRouter } from 'react-router-dom';

// WithRouter
// 라우트로 사용된 컴포넌트가 아니어도 location, history, match 객체에 접근할 수 있게 해준다.
const WithRouterSample = ({ location, match, history }) => {
    return (
        <div>
            <h4>로케이션</h4>
            <textarea
                value={JSON.stringify(location, null, 2)}
                rows={7}
                readOnly={true}
            />
            <h4>매치</h4>
            <textarea
                value={JSON.stringify(match, null, 2)}
                rows={7}
                readOnly={true}
            />
            <button onClick={() => history.push('/')}>집으로</button>
        </div>
    );
};

export default withRouter(WithRouterSample);

// Profile.js 파일에 아래와 같이 추가해준다.

import { withRouter } from 'react-router-dom';
import WithRouterSample from './WithRouterSample';

const Profile = ({ match }) => {
    const { username } = match.params;
    const profile = data[username];
    if (!profile) {
        return <div>사용자 없음</div>;
    }
    return (
        <div>
            <h3>
                {username}({profile.name})
            </h3>
            <p>{profile.description}</p>
            <WithRouterSample />
        </div>
    );
};

export default withRouter(Profile);

현재 경로와 Link에서 사용하느 경로가 일치하는 경우 특정 스타일 또는 CSS클래스를 적용할 수 있는 컴포넌트이다. NavLink에서 링크가 활성화되었을 때의 스타일을 적용할 때는 activeStyle를 사용하고, CSS 클래스를 적용할 때는 activeClassName 값을 props로 넣어준다.

import { NavLink } from 'react-router-dom';

Profiles.js에서 NavLink를 import에 추가해주고, 스타일 설정 값을 만든 후 NavLink 컴포넌트에 props activeStyle을 지정해준다.

// Profiles.js
import { Link, Route, NavLink } from 'react-router-dom';

const Profiles = () => {
    const activeStyle = {
        background: 'black',
        color: 'white',
    };
    return (
        <div>
            <h3>사용자 목록 :</h3>
            <ul>
                <li>
                    {/* <Link to="/profiles/kyungil">kyungil</Link> */}
                    <NavLink activeStyle={activeStyle} to="/profiles/kyungil">
                        kyungil
                    </NavLink>
                </li>
                <li>
                    {/* <Link to="/profiles/academy">academy</Link> */}
                    <NavLink activeStyle={activeStyle} to="/profiles/academy">
                        academy
                    </NavLink>
                </li>
            </ul>
            <Route
                path="/profiles"
                exact={true}
                render={() => <div>사용자 선택</div>}
            />
            <Route path="/profiles/:username" component={Profile} />
            {/* <WithRouterSample /> */}
        </div>
    );
};
profile
프론트엔드 개발자

0개의 댓글