같이 성장하는 프로그래밍

1-3 리액트 라우터 API 문서 (useLocation) 본문

react router dom

1-3 리액트 라우터 API 문서 (useLocation)

프설남 2020. 10. 19. 05:09
반응형

useLocation

  The useLocation hook returns the location object that represents the current URL. You can think about it like a useState that returns a new location whenever the URL changes.

  This could be really useful e.g. in a situation where you would like to trigger a new “page view” event using your web analytics tool whenever a new page loads, as in the following example:

 

 

useLocation

  useLocation 훅은 현재의 URL을 대표하는 location 객체를 반환한다. 너는 URL이 바뀔 때마다 새로운 location이 반환되는 useState 처럼 생각할 수 있다.

  다음의 예시와 같이, 이것은 예를 들어 새로운 페이지가 로드될 때마다 web analytics tool(웹 분석 도구)를 사용하는 새로운 "페이지 모습" 이벤트를 작동시키고 싶어하는 상황에서 정말로 유용할 수 있다.

 

 

--설명을 보시려면 더 보기를 눌러주세요--(스크롤 길이 주의)

더보기

--loaction 객체란? 

 

  useLocation이 location 객체를 반환한다고 하니 직접 불러오고 콘솔창에 찍어보겠습니다.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useLocation
from "react-router-dom";
export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
        </ul>
        <hr />
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/about">
            <About />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}
function Home() {
  
  return (
    <div>
      <h2>Home</h2>
    </div>
  );
}
function About() {
  let locationObj = useLocation(); //useLocation()은 location 객체를 반환하므로
                                //locationObj 변수에 location 객체를 저~장
  
  console.log(locationObj);
  
  return (
    <div>
      <h2>About</h2>
    </div>
  );
}
 
cs

(코드 1) location 객체를 알아보기 위한 코드

 

  (코드 1)을 보시면 7행에 react-router-dom의 useLocation을 import 하였고,

42행 About 컴포넌트에 location 객체를 locationObj 변수에 저장하고,

46행에서 loactionObj에 무엇이 담겨있는 지 확인하기 위해 콘솔 창에 출력하는 코드입니다.

 

  즉, About링크를 누르면 locationObj에 location객체가 저장되고 locationObj가 콘솔에 출력됩니다.

 

 

(그림 1) locationObj 를 확인하는 그림

  (그림 1)은 About 화면으로 이동시키니 URL은 "bnpsd.csb.app/about" 여기로 이동을 하게 되었고 이 페이지가 가지고 있는 location 객체의 정보는 locationObj가 저장하고 그걸 콘솔 창에 출력하고 있습니다.

 

  그럼 이제 가장 중요한 location 객체는 도대체 무엇을 가지고 있는 지 하나하나 살펴보도록 합시다.

 

  1. pathname : 보시면 URL의 도메인 다음의 /를 식별자로써 /부터의 문자열이 pathname으로 들어갑니다.

여기선 "/about" 이 됩니다.

 

1
2
3
4
5
6
7
8
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about?id=10">About</Link> //"/about"에서 "/about?id=10"으로 변경
          </li>
        </ul>
cs

 

(코드 2) '코드 1' 에서의 18번 행 코드 변경

(그림 2) location 객체의 search를 설명하기 위한 그림

  URL 주소가 "bnpsd.csb.app/about?id=10" 으로 변경되었습니다. 여기서 search의 역할을 알 수 있습니다.

  2. search : URL에서 ?가 식별자로써 ?부터 나오는 문자열 전부입니다. 여기선 '?id=10' 가 해당됩니다.

여기서 주의하셔서 보실 부분은 pathname이 /로부터 끝까지가 아니라 도중에 ?라는 식별자를 만날 때까지 이라는 겁니다.

 

 

  그렇다면 여기서 이 녀석이 하는 일은 무언인가? pathname은 페이지 이동을 위한 state입니다.

search는? 예시를 들어서 설명을 해보겠습니다.

 

(예시)

게시판이 있습니다.

게시판 목록 URL : /board

게시물 내용 화면 URL : /content

게시물 번호의 변수명 : id

라고 가정하고 1번 게시물부터 10번 게시물까지 있는 예시입니다.

그리고 3번 게시물을 선택했습니다. 그럼 이동하는 URL "/content"에 ?id=3 를 뒤에 붙입니다.

"/content?id=3" 이렇게 보냅니다.

그럼 content의 컴포넌트에서 이 loaction 객체의 search를 읽고 ? 다음의 id=3 을 읽어내서 아! 게시물 번호가 3번인 게시물을 렌더링 하겠습니다. 라고 코드를 짜는 데 이용됩니다.

 

즉, URL에 정보를 포함해서 화면이동을 하는 역할입니다.

 

1
2
3
4
5
6
7
8
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about#id=10">About</Link> // ? 를 # 으로 변경
          </li>
        </ul>
cs

(코드 3) '코드 2'에서 ? 를 #으로 변경

 

(그림 3) location 객체의 hash를 설명하기 위한 그림

  URL 주소가 "bnpsd.csb.app/about#id=10" 으로 변경되었습니다. 여기서 hash의 역할을 알 수 있습니다.

  3. hash : URL에서 #가 식별자로써 #부터 나오는 문자열 전부입니다. 여기선 '#id=10' 가 해당됩니다.

여기서도 주의하셔서 보실 부분은 pathname이 /로부터 끝까지가 아니라 도중에 #라는 식별자를 만날 때까지 이라는 겁니다.

 

hash의 쓰임새도 짐작이 가듯이 search와 같은 쓰임새입니다.

다만, 차이점은 식별자가 ? 냐 # 냐 차이입니다.

 

※ search와 hash는 동시에 사용하실 수 있으십니다. 

예시) "bnpsd.csb.app/about?date=20201019#id=10"

 

  4. state : search나 hash처럼 표면적으로 URL에 붙여서 보내는 정보가 아닌 숨겨서 또는 코드로 보내는 정보정도로 이해하시면 되겠습니다. 

 

  4-1. Link 태그를 쓰거나 history.push, history.replace 등으로 페이지 이동을 하실 때 쓰실 수 있습니다.

먼저 Link부터 형태를 보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
         <ul>
          <li>
            <Link to={{                      // to 속성에 넣는 값을 변경
                pathname: "/",
                search: "?sort=name",
                hash: "#the-hash",
                state: { 
                         key1: "value1"
                         key2: "value2" 
                       }
              }}>Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
        </ul>
cs

(코드 4) Link 태그의 to 속성 변경 코드

  (코드 4)는 (코드 1)의 15번 행의 Link 태그를 변경한 것 입니다.

  (코드 1)에서는 to 속성에 그냥 string을 넣었습니다.

  하지만 이번에는 location 객체를 내가 각각 지정해서 넣습니다.

  이렇게 보내면 URL은 "도메인/?sort=name#the-hash" 가 될 것이고 location 객체안의 state에는 

{

   key1 : "value1",

   key2 : "value2"

}

  가 채워질 겁니다.

  다음 결과 그림을 보시겠습니다.

 

 

(그림 4) location 객체의 state를 설명하기 위한 그림

 

  보시는 바와 같이 URL이 "bnpsd.csb.app/?sort=name#the-hash" 로 이동이 되었고 location 객체도 위에서 예상했듯이 결과가 표시되었습니다. 이렇게 코드 상으로 state를 보낼 때 사용하게 됩니다.

 

 

    4-2. history.push와 history.replace는 이전 글의 설명과 같이,

          history.push(path,[state]), history.replace(path,[state]) 로 사용됩니다.

          그러므로 보시기에도 [state]을 이용하기 싶으시죠?? 네 맞습니다.

  (코드 4)와 똑같은 기능을 하도록 코드를 짜보겠습니다.

history.push(

   "/?sort=name#the-hash",

   {

      key1 : "value1",

      key2 : "value2"

   }

)

 

history.replace(

   "/?sort=name#the-hash",

   {

      key1 : "value1",

      key2 : "value2"

   }

)

 

  이렇게 사용하면 (그림 4)와 같은 결과를 얻으실 수 있으십니다.

  마지막으로, 그럼 왜 state를 사용해서 보내냐입니다. 제가 아는 지식에서는 첫번째로는 URL에 보여서는 안되는 중요한 정보를 넘겨줄 때 state로 숨겨서 보낸다. (애초에 엄청 중요한 정보면 이렇게 보내지 않겠지만요..)

  두번째로는 URL은 글자 수 제한이 있습니다. 255자였던가.. 검색해보니 2083자라는 군요!

그러므로 state로 보낼 때는 글자 수 제한이 없습니다!

 

 

5. key : 이전 글과 이어지는 내용입니다. 간단히 history stack에서 이 해당하는 location 객체를 찾기위한 고유의 문자열 키입니다.

 

  (그림 4)의 Home 링크를 3번 누른다고 해봅시다. 화면의 내용은 바뀝니까? 바뀌지 않습니다.

  페이지 이동은 합니까? 네 합니다. 즉, 새로고침이라고 하죠.

  그럼 여기서 3번 같은 페이지로 페이지 이동이 되었습니다.  그럼 history stack에는 차례대로 이 3번의 Home 정보가 쌓입니다. 그래서 History가 몇 번째 스택에 있는 history 객체인지 알기 위해서는 이 key이용한다고 합니다.  

 

(그림 5) Home 링크를 3번 누른 그림

  보시는 바와 같이 모든 state들은 같은 값을 가지지만 오직 key만 랜덤의 6글자 문자열을 가지게 됩니다.

 

  그리고 마지막으로 location 객체는 어디서 많이 보신 모습 아닙니까?

  이전 글인 "1-2 리액트 라우터 API 문서 (useHistory의 state)" 에서의 (그림 10)과 거의 같습니다!

 

(그림 6) 이전 글에서의 (그림 10)의 history 객체 안의 location

  친절히 또 복사해왔습니다. 헤헤

  이전 글을 안 보신 분들은 (그림 2)가 history 객체 안에 있는 location이고 (그림 1)은 location 객체 안에 있는 겁니다. 직관적으로 보셔도 key를 제외하고는 모두 같죠?

  같지만 따로 있는 이유가 있을 겁니다. 계속 저와 함께 알아가보십시다. : )

 

 

 


 

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
import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  useLocation
from "react-router-dom";
 
function usePageViews() {
  let location = useLocation(); //location 객체를 location 변수에 저~장
 
 
  React.useEffect(() => {                      //react hooks의 하나인 useEffect
 
    ga.send(["pageview"location.pathname]);  //ga 라는 건 google Analytics (구글 분석)
                                               //으로써 웹 분석 도구입니다.
                                               //간단히 트래픽 등 관리하기 위한 도구입니다.
  }, [location]);                              //location 값이 변경될 때마다 useEffect가 실행됩니다.                                            
}
 
function App() {
  usePageViews();
  return <Switch>...</Switch>;
}
 
ReactDOM.render(
  <Router>
    <App />
  </Router>,
  node
);
cs

(코드 5) useLocation 예시 코드 1

 

  먼저 코드를 보시면 React.useEffect() 가 있습니다. 이건 react에 내장되어있는 react hooks의 하나인 useEffect() 입니다.

  간단한 사용처는 react의 생명주기(life cycle)의 기능과 같은 기능을 하는 녀석입니다. 절대 같은 건 아닙니다! 함수형 컴포넌트에서 생명주기를 사용하기 위해 만들어진 기능입니다.

  그리고 ga.send() 는 먼저 ga 라는 건 google analytics 의 약자이며, web analytics tool(웹 분석 도구) 중 하나입니다. 저도 잘 몰라서 직접 들어가서 만들어봤습니다.

 

(그림 7) 구글 분석 도구 화면

  처음에 회원가입처럼 정보 입력하고 내가 분석할 사이트를 입력해서 들어갑니다. 그러면 처음에 이렇게 추적 코드라는 걸 보여줍니다. 이걸 내가 분석하고 싶은 해당 사이트 html 소스에 붙여넣으면 된답니다.

 

(그림 8) 구글 분석 도구 홈 화면

  홈 화면을 보니 이렇게 내가 맨 처음 설정할 때 입력한 사이트에 대한 트래픽 분석이 가능합니다. 사용자 위치 등등이요. ㅎㅎ 여기서 트래픽이라는 용어는 서버의 전송량을 뜻합니다. 내가 개인 사이트를 열려면 24시간 작동하는 서버 컴퓨터가 필요할거고 그 서버의 성능은 한정적입니다. 즉 내가 구성해놓은 서버는 동시 접속이 100명까지만 가능한데 200명이 접속하게 되면 서버가 터지는거죠 ㅠㅠ 즉, 사용자가 많아져서 트래픽이 증가한다가 됩니다.

 

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
import React from "react";
import ReactDOM from "react-dom";
import {
  BrowserRouter as Router,
  Switch,
  useLocation
from "react-router-dom";
 
function usePageViews() {
  let location = useLocation(); //location 객체를 location 변수에 저~장
 
 
  React.useEffect(() => {                      //react hooks의 하나인 useEffect
 
    ga.send(["pageview"location.pathname]);  //ga 라는 건 google Analytics (구글 분석)
                                               //으로써 웹 분석 도구입니다.
                                               //간단히 트래픽 등 관리하기 위한 도구입니다.
  }, [location]);                              //location 값이 변경될 때마다 useEffect가 실행됩니다.                                            
}
 
function App() {
  usePageViews();
  return <Switch>...</Switch>;
}
 
ReactDOM.render(
  <Router>
    <App />
  </Router>,
  node
);
cs

(코드 5) useLocation 예시 코드 1 복사

 

 그래서 ga.send() 함수를 이용해서 내 사이트안에서 location 값이 바뀔 때마다 구글 분석 도구에 지금의 location.pathname을 보내는 거고 이 정보를 토대로 누가 어디서 방문을 했고 몇 명이 방문하고 있는 지를 알 수 있는 것 같습니다. 

  그러므로 URL의 정보를 가지고 있는 loaction 객체가 유용하게 쓰인다는 뜻입니다.

 


 

location

Locations represent where the app is now, where you want it to go, or even where it was. It looks like this:

 

 

location

location은 앱이 지금 어딨는지, 너가 location이 어디로 가길 원하는 지, 어디에 있었는 지를 나타낸다. 다음과 같은 모습이다.

 

 

1
2
3
4
5
6
7
8
9
{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere',
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}
cs

(코드 6) Location 예시 코드 2

 

맨 위에 useLocation에 대해 알아보실 때 location 객체가 무엇을 가지고 있는 지 찾아봤습니다.

(코드 6)은 위에서 보신 것처럼 loaction 객체가 가지고 있는 state들을 보여주는 겁니다.

 

 


 

The router will provide you with a location object in a few places:

  • Route component as this.props.location
  • Route render as ({ location }) => ()
  • Route children as ({ location }) => ()
  • withRouter as this.props.location

It is also found on history.location but you shouldn’t use that because it’s mutable. You can read more about that in the history doc.

A location object is never mutated so you can use it in the lifecycle hooks to determine when navigation happens, this is really useful for data fetching and animation.

 

 

라우터는 몇 군데에서 location 객체를 너에게 제공할 것이다.

  • <Route> 컴포넌트에서는 this.props.location 으로 접근
  • <Route>의 render 속성에서는 ({ location }) => () 으로 접근
  • <Route>의 children 속성에서는 ({ location }) => () 으로 접근
  • <withRouter> 에서는 this.props.location 으로 접근

  location 객체는 history.location에서도 발견된다. 그러나 history.location을 사용해서는 안된다! 왜냐하면 history.location은 변하기 때문이다. history 문서에 있는 그것에 대해 더 읽어볼 수 있다.

  한 location 객체는 절대 변하지 않는다. 그래서 너는 location 객체를 화면이동을 결정하는 생명주기 훅스안에서 사용할 수 있다. 이것은 정말로 데이터를 수집하거나 애니메이션에 유용하다.

 

1
2
3
4
5
componentWillReceiveProps(nextProps) {
  if (nextProps.location !== this.props.location) { // 다음 화면의 location과
// 현재 화면의 location을 비교
    // navigated!
  }
}
cs

(코드 7) location 예시 코드 3

 

  여기서 가장 중요하게 보셔야할 부분은 생명주기입니다. 리액트의 생명주기에서 history.location은 화면이 완전히 이동할 때까지 유지가 안되고 바로 변하기 때문에 쓰지말아야하고 location 객체는 화면이 완전히 이동하기 전까지 유지되므로 다음 이동할 location과 현재 location을 비교하는 데 적합하다는 내용입니다.

 

 


 

You can provide locations instead of strings to the various places that navigate:

  • Web Link to
  • Native Link to
  • Redirect to
  • history.push
  • history.replace

Normally you just use a string, but if you need to add some “location state” that will be available whenever the app returns to that specific location, you can use a location object instead. This is useful if you want to branch UI based on navigation history instead of just paths (like modals).

 

 

  화면을 이동케하는 여러가지 장소들에게 문자열 대신에 location 객체를 제공할 수 있다.

  • Web Link to <Link to={location} />
  • Native Link to <NavLink to={location} />
  • Redirect to <Redirect to={location} />
  • history.push history.push(location)
  • history.replace history.replace(location)

 

  보통 너는 그냥 문자열을 쓴다. 그러나 너가 앱이 특정한 location으로 반환되어야 할 때마다 조금의 "location state"(여기서는 pathname, search, hash, state 등을 뜻함) 추가하기를 필요로 한다면 그냥 문자열을 쓰는 것 대신에 location 객체를 사용할 수 있다.

  이것은 (모달과 같은) 단순한 path 대신에 화면이동 history에 기초한 UI를 갈라지게 원한다면 유용하다.

 

 

--설명을 보시려면 더 보기를 눌러주세요--

더보기

--모달이란? 

 

  모달이란 간단히 다이얼로그 창이라고 생각하시면 됩니다. alert 알림창 같은 팝업 창이라고 생각하시면 됩니다.

즉, 여기서는 모달이 단순한 path를 입력해서 팝업 창이 뜬다고 설명하는 겁니다.

 

 

--UI를 갈라지게 원한다면? 

 

  location 객체의 search의 게시판 예시를 설명했었습니다. (그림 2)의 밑부분에 적혀있습니다.

그러니까 Route에서 받는 url 형식은 같습니다.

 

<Route path="/content" />

 

  그러나 게시판의 번호에 따라 search의 id 값이 다를겁니다.

 

3번 게시물 <Link to="/content?id=3" />3번 게시물 <Link to={ {pathname : "/content" , search : "?id=3"  } } />

 

5번 게시물 <Link to="/content?id=5" />3번 게시물 <Link to={ {pathname : "/content" , search : "?id=5"  } } />

 

  이렇게 말입니다. 즉 이럴 때 location의 state를 이용해서 어디선가 변수를 받아와서 search나 hash에 그 받아온 변수를 넣을 수도 있을 것이고 등등 화면이동을 갈라지게 만들 수 있다는 겁니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
// usually all you need
<Link to="/somewhere"/>
 
// but you can use a location instead
const location = {
  pathname: '/somewhere',
  state: { fromDashboard: true }
}
 
<Link to={location}/>
<Redirect to={location}/>
history.push(location)
history.replace(location)
cs

(코드 8) location 예시 코드 4

 

  (코드 8)은 마찬가지로 location 객체를 이용해서 Link, NavLink, Redirect, history.push, history.replace 등에 사용할 수 있다는 예시 코드입니다.

 


 

Finally, you can pass a location to the following components:

  • Route
  • Switch

This will prevent them from using the actual location in the router’s state. This is useful for animation and pending navigation, or any time you want to trick a component into rendering at a different location than the real one.

 

 

마지막으로 너는 다음 컴포넌트들에 location을 통과시킬 수 있다.

  • Route
  • Switch

이것은 router의 state에 있는 실제 location을 사용하는 것을 막을 것이다. 이것은 애니메이션 그리고 화면이동 보류에 유용하거나 언제든 너가 컴포넌트를 실제가 아닌 다른 location에 렌더링하도록 속이고 싶을 때 유용하다.

 

  

 

  이 말을 해석하자면 먼저 react는 SPA(Single Page Application)입니다. 페이지가 한 개인 어플리케이션이라는 뜻입니다.

  어?! 아니 Home 버튼 About 버튼 만들어서 화면이동하고 하잖아 페이지가 벌써 2개구먼!!! 라고 이해하셨다면 '속이고 싶을 때 유용하다.' 에 글을 읽고 계시는 분도 속으신겁니다. ㅎㅎ

  실제로는 하나의 페이지로 이루어져있는데 Route, Switch 덕분에 이 싱글페이지 안에서 화면이동이 나는 것처럼 보여주는 겁니다.

 

 


정리

 

1. useLoaction 은 location 객체를 반환한다.

 

2. location 객체에는

    2-1. pathname : URL에 도메인다음의 / 부터의 문자열

    2-2. search : pathname다음의 ?부터의 문자열

    2-3. hash : pathname다음의 #부터의 문자열

    2-4. state : location 객체로 화면이동을 시킬 때 코드 상으로 보내는 객체

    2-5. key : history stack에서 해당 location 객체를 찾기위한 고유키

 

3. 화면이동 시 보통 단순한 문자열 path를 통과시키지만 세세하게 컨트롤하기 위해 location 객체를

   통과시킬 수도 있다.

 

4.  리액트의 생명주기에 관해서 location을 비교할 때는 history의 location은 현재 location값이 유지되지

   않고 변하므로 변하지 않고 유지되는 location 객체를 사용해야한다.

 

5. location 객체로 화면이동을 시키는 건 Route와 Switch 덕분에 화면이동이 되어지는 것처럼 보일 뿐이다.

 

 


맺음말

 

  일주일이 지나서 토, 일요일 하루에 1개씩 한 주에 2개씩 블로그 글을 쓰려고 했습니다만, 일이 바쁜 관계로 이번 주에는 1개의 글만 올리게 되었습니다 ㅠ

  그리고 제 글을 끝까지 읽어주셔서 감사합니다!

  다음 글은 useParams()에 대해 설명하는 글을 써보도록 하겠습니다!!

  지적과 오타 등 댓글로 남겨주시면 감사하겠습니다!

반응형
Comments