React 에서 React-Router 없이 Navigation 해보고 싶었다...

박정훈·2022년 1월 12일
1

React

목록 보기
1/10

이곳을 보면서 알아갔다.

Window

Dom 문서를 담은 창... 그럼 Dom은?

Document Object Model

브라우저가 HTML 웹 페이지를 인식하는 방식을 자기들이 이해 할 수 있게 계층화 시켜서, 트리구조로 만든 Object Model 이다.
그러니까 단적으로?? 우리가 아는 HTML 이다. 우린 Dom 을 통해서 JS 에서 HTML의 태그에 접근 하고, 수정 할 수 있다.

다시 돌아와서..
JS 코드에서 접근 가능한 window는 현재 스크립트가 작동 중인 창을 나타낸다. JS에서 브라우저의 기능들에 접근하고, 제어하고자 할 때 Window객체(Browser Object Model)가 이를 제공해준다.

Window.location

현재 Document 의 location에 대한 정보를 담고 있다. local 에서 window.location 을 찍어보면 Location 에 관한 정보가 쥬르르륵~ 나온다.그리고 여기서 중요한 프로퍼티 중 하나인 pathname 으로 콘텐츠를 보여주거나 말거나 하게 될 것이다! pathname은 최초 / 뒤에 나오는 path를 담고 있다.

반복 사용하게 될 Route

pathname 의 여부에 따라서 페이지를 보여줄 지 말지를 결정하게 된다. 경로가 맞지 않다면 null 처리 되서 빈 페이지가 보인다.

// Route.tsx
import { ReactNode } from "react";

interface RouteProps {
  path: string;
  children: ReactNode;
}

const Route = ({ path, children }: RouteProps) => {
  return window.location.pathname === path ? <>{children}</> : null;
};

export default Route;

이렇게 사용

      <Route path="/">
        <Component />
      </Route>
      <Route path="/blank">
        <Component />
      </Route>

blank 페이지로 이동 후 location 이다.
pathname 이 /blank 로 찍혔다.

전체 페이지 리로딩 방지

a 태그는 다른 URL로 연결할 수 있는 하이퍼링크를 만든다. 그리고 href 경로의 새 창을 다운로드 하는 특징은 full rerendering 을 일으킨다.

// Link 컴포넌트를 만들어주자. Link.tsx
import React, { MouseEvent, ReactNode } from "react";

interface LinkProps {
  href: string;
  children: ReactNode;
}

const Link = ({ href, children }: LinkProps) => {
    const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
        event.preventDefault();
    }
  return <a href={href} onClick={onClick}>{children}</a>;
};

export default Link;

URL 바꿔주기

페이지 리로딩 없이 dynamically 하게 콘텐츠를 바꿔줄 수 있다면 URL 을 바꿔주는 것은 어떤 의미를 가지는가? 단순히 사용자가 특정 페이지의 위치를 북마크에 추가해 다시 방문하기를 기대하기 때문이다. URL을 수동으로 업데이트 하는 방법은 history.pushState 가 있다.

// Link.tsx
const Link = ({ href, children }: LinkProps) => {
    const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
        event.preventDefault();
        window.history.pushState({}, "", href)
      	console.log(window.location);
    }
  return <a href={href} onClick={onClick}>{children}</a>;
};

export default Link;

다시 로그를 찍어봤다. 현재 Lcoation 은 로컬/blank 로 바뀌어 있는 것을 확인 했다.
pathname 또한 당연히 /blank다. 물론 아직 페이지는 안바뀐다. 경로만 바뀌었다.

Route 에게 URL 이 바뀌었다고 알려주자

popstate 이벤트는 window's 의 history가 바뀔시 발생한다. 그렇지만 MDN PopStateEvent 에서 popstate 는 pushState()를 호출 하는 것으로는 발생하지 않는다고 한다. 그래서인가? 직접 PopstateEvent 객체를 생성 해 준다. 이를 주석처리 하고 실행 해 보면 페이지는 이동하지 않는다.
popstate 이벤트 객체를 생성해 주고, 이를 dispatch 해 줘야 한다. 이벤트 객체를 생성했다면 반드시 실행 시켜줘야 한다.

// Link.tsx
const Link = ({ href, children }: LinkProps) => {
    const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
        event.preventDefault();
        window.history.pushState({}, "", href)
        const navEvent = new PopStateEvent('popstate');
    	window.dispatchEvent(navEvent);
      ...
      ...

이제 popstate 이벤트가 발생한다! Route.ts 로 가서 popstate 발생 시 콜백 함수를 등록 시켜주자.

// Route.tsx
import { ReactNode, useEffect, useState } from "react";

interface RouteProps {
  path: string;
  children: ReactNode;
}

const Route = ({ path, children }: RouteProps) => {
  // URL 을 추적하고, 변경이 있을시 다시 그려준다.
  const [currentPath, setCurrentPath] = useState(window.location.pathname);

  useEffect(() => {
    const onLocationChange = () => {
      setCurrentPath(window.location.pathname);
    };

    // listen for popstate event
    window.addEventListener("popstate", onLocationChange);

    // clean up event listener
    return () => {
      window.removeEventListener("popstate", onLocationChange);
    };
  }, []);

  return currentPath === path ? <>{children}</> : null;
};

export default Route;

잘 동작한다 :) React-Router도 사용 해 봤는데 그것보다 더 재밌는 시간이었다. 전에는 빨리 사용하고 싶어서 단순하게 사용법만 알아내고 사용했어서 그런가? 엘리스 AI 트랙을 시작했다. 공학은 수단과 방법을 가리지 않고 해내는 것이 중요하다고 하더라. 갑자기 뜬금 없는 말이긴 한데 그냥 이글을 정리해 보고 느낀점이다.

profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글