티스토리 뷰

SW프로그래밍/React

[React]SPA , React-Router

고랑이. 2021. 4. 27. 17:54

SPA

(Single Page Application)

한 개의 페이지로 이루어진 애플리케이션으로

이벤트에 따라 동적으로 화면을 바꿔가며 최소한의 요소만 변경이 일어난다. 

 

기존의 웹 브라우저는 화면 전환이 일어날 때마다 HTML을 서버에 새로 요청하면서 불필요한 로딩이 있었던 반면에
SPA는 애플리케이션을 브라우저에 불러와 필요한 부분의 렌더링을 브라우저가 담당하여 서버에 부하를 줄여준다. 

 

https://lvivity.com/single-page-app-vs-multi-page-app


 

라우팅 

- 다른 주소에 다른 화면을 보여주는 것. 

- 서버에서 사용자에게 제공하는 페이지는 한종류이지만, 현재 사용자 브라우저의 주소 상태에 따라 다양한 화면을 보여줄 수 있다.

yarn add react-router-dom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/index.js
// BrowserRouter로 컴포넌트로 App을 감싸기. 
 
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import App from './App';
 
ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
 
 

 

 

react-router 기본

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {Route, Link} from 'react-router-dom';
import MyComponent from './MyComponent';
 
const App = () => {
    return(
        <div>
            <ul>
                <li>
                    <Link to='/myComponent'>my component</Link> {/* <a></a> 와 같음 */}
                </li>
            </ul>
            
            <Route 
              path='/myComponent'        //경로
              component={MyComponent}    //경로에 보여줄 페이지
              exact            //path가 같을때만 컴포넌트로 이동됨. (default : true)
            />
        </div>
    )
};
 
export default App;
 

 

하나의 컴포넌트에 여러 경로를 사용하는 경우.

<Route path={['/path1','/path2']} component={MyComponent}/>

 

경로에 파라미터를 사용하는 경우.

라우트로 사용되는 컴포넌트에서 받아 오는 match 객체 안의 params 값을 참조.

match : 현재 컴포넌트가 어떤 경로 규칙에 의해 보이는지에 대한 정보. 

 

라우트 :  <Route exact path="/profile/:username" component={Profile} />
경로 : /profile/gildong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import React from 'react';
 
const data = {
    gildong:{
        name'홍길동',
        description: '고전 소설 홍길동전의 주인공'
    }
}
 
const Profile = ({match}) => {
    const {username= match.params;
    const profile = data[username];
    if(!profile){
        return <div>존재하지 않는 사용자입니다.</div>;
    }
       
    return(
        <div>
            <p>profile</p>
            <h3>{username}({profile.name})</h3>
            <p>{profile.description}</p>
        </div>
    )
}
export default Profile;
 
 

 

URL 쿼리를 사용하는 경우.

라우트로 사용된 컴포넌트에게 props로 전달된 location객체에서 쿼리를 가져옴. (location.search)

yarn add qs		//쿼리 문자열을 객체로 변환하여 사용. 

 

라우트 : <Route path="/path" component={Path} />
경로 : /path?username=kkk&boolean=true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React from 'react';
import qs from 'qs';
 
const Path = ({location}) => {
    console.log(location);
 
    const query = qs.parse(location.search, {
        ignoreQueryPrefix: true //?생략.
    })
    const showDetail = query.boolean === 'true';  //쿼리의 파싱 결과값은 문자열 입니다.
    
    return(
        <div>
            username : {query.username}
            <br/>
            true string: {query.boolean}
            <br/>
            true boolean : {showDetail && <span>TURE 입니다.</span>}
        </div>
    )
}
 
export default Path;
 

* 쿼리스트링으로 전달된 값은 무조건 문자열로 넘어가기 때문에, 숫자나 논리형 자료값을 사용하는 경우 변환 단계가 필요하다. 

 

 


서브 라우트

라우트 내부에 또 라우트를 정의하는 것

 

라우트 : <Route path="/profiles" component={Profiles} />

경로 : /profiles →  /profiles/gildong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import {Route, Link} from 'react-router-dom';
import MyComponent from './MyComponent';
const Profiles = () => {
    return(
        <div>
            <ul>
                <li><Link to="/profiles/velopert">velopert</Link></li>
                <li><Link to="/profiles/gildong">gildong</Link></li>
            </ul>
            
            <Route 
              path='/profiles'        
              exact
              render = {() => <div>사용자를 선택해 주세요.</div>}
            />
            <Route path='/profiles/:username' component={Profile} />
            
        </div>
    )
}
export default Profiles;
 

파라미터가 없을 때에는 "사용자를 선택해 주세요"를 렌더링하고, 

파라미터가 있을 때 Profile 컴포넌트를 연결한다.

 


리액트 라우터 부가 기능 

History

라우트로 사용된 컴포넌트에 match, location과 함께 전달되는 props 중 하나. 

history의 함수를 이용해서 특정 버튼을 눌렀을 때 뒤로 가거나, 로그인 후 화면을 전환하거나, 다른 페이지로 이탈하는 것을 방지하는 것이 가능.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React, { Component } from 'react';
 
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() {
        console.log(this.props.history);
        return (
            <div>
                <button onClick={this.handleGoBack}>뒤로</button>
                <button onClick={this.handleGoHome}>홈으로</button>
            </div>
        );
    }
}
 
export default HistorySample;
 


WidthRouter

Hoc(Higher-order Component)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React from 'react';
import { withRouter } from 'react-router-dom';
 
const WithRouterSample = ({locationmatchhistory}) => {
    return(
        <div>
            <h4>location</h4>
            <textarea
                value={JSON.stringify(locationnull2)}
                row={7}
                readOnly
            />
 
            <h4>match</h4>
            <textarea
                value={JSON.stringify(matchnull2)}
                row={7}
                readOnly
            />
            <button onClick={() => history.push('/')}>홈으로</button>
        </div>
    )
}
 
export default withRouter(WithRouterSample);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React from 'react';
import { Route, Link } from 'react-router-dom';
import Profile from './profile';
import WithRouterSample from './WithRouterSample';
 
const Profiles = (props) => {
    console.log(props);
    return(
    <div>
        <h3>사용자 목록: </h3>
        <ul>
            <li><Link to="/profiles/velopert">velopert</Link></li>
            <li><Link to="/profiles/gildong">gildong</Link></li>
        </ul>
 
        
        <Route 
            path="/profiles"
            exact
            render = {() => <div>사용자를 선택해 주세요</div>}
            //Route에 component대신 render을 넣을 수 있음.
        />
        <Route path="/profiles/:username" component={Profile} />
 
        <WithRouterSample />
        
    </div>     
    )};
 
export default Profiles;

* match의 params가 비어있는 이유는 widthRouter를 사용하는 라우트 컴포넌트가 기준이기 때문,

  profile에서 widthRouter를 사용한다면 params에 username이 있음. 


 

Switch

여러 Route를 감싸서 그 중 일치하는 단 하나의 라우트만 렌더링 시킴. 

Switch를 사용하면 특정하지 않은 경로로 이동했을 때 Not Found 페이지를 처리할 수 있음.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Switch>
    <Route path="/" component={Home} exact={true}/>
    <Route path={['/about','/info']} component={About} />
    <Route path="/profiles" component={Profiles} />
    <Route path="/history" component={HistorySample}/>
    <Route 
    //path를 따로 정의하지 않으면 모든 상황에서 렌더링됨
        render = {({location}) => (
            <div>
                <h2>이 페이지는 존재하지 않습니다.</h2>
                <p>{location.pathname}</p>
            </div>
        )}
    />
</Switch>
 


 

NavLink

현재 경로와 Link에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 CSS클래스를 적용할 수 있는 컴포넌트

activeStyle : 링크가 활성화 되었을 때 스타일 적용

activeClassName : CSS클래스 적용

1
2
3
4
5
6
7
8
9
const activeStyle = {
    background : "black",
    color : "white"
}
 
<ul>
    <li><NavLink activeStyle={activeStyle} to="/profiles/velopert">velopert</NavLink></li>
    <li><NavLink activeStyle={activeStyle} to="/profiles/gildong">gildong</NavLink></li>
</ul>
 


참조 :

리액트를 다루는 기술(김민준 / 길벗)

www.daleseo.com/react-router-basic/

'SW프로그래밍 > React' 카테고리의 다른 글

[React] api 호출, Axios  (1) 2021.05.12
[react List] react-virtualized 스크롤 핸들링  (0) 2021.04.29
[React]immer  (0) 2021.04.26
[React] 컴포넌트 성능 최적화  (0) 2021.04.26
[React]컴포넌트 스타일링  (0) 2021.04.08
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함