React.js react router dom으로 SPA 구축하기 (이론+)

강정우·2023년 1월 31일
0

react.js

목록 보기
36/45
post-thumbnail
post-custom-banner

404page 작성하기

  • 사용자가 정해진 path말고 임의의 경로를 검색하여 들어올 때 찾을 수 없음을 나타내주어야 한다.
    그렇다면 당연히 Route들이 모여있는 Routes 태그로 가야한다.

  • 바로 astarisk를 사용하여 "wild card"라고도 부른다.

<Routes>
  	<Route path={"/"} exact><Redirect to={"/index"}/></Route>
						...
	<Route path={"*"}><NotFound/></Route>
</Routes>

프로그래밍방식 탐색 구현

  • 무슨 말이냐 사용자가 form을 작성하여 제출을 했을 때 ok modal을 띄울 수도 있고 뒤로가기나 다른 path에 보낼 수도 있다.
  • 즉, 여기서 필요한 것이 programtic한 내비게이션이다. 탐색 작업을 트리거하고 코드에서 programtic하게 사용자를 나가게 하는 것이다.
    따라서 사용자가 다른 곳으로 나가기 위해 클릭하는 링크가 아니라 입력된 데이터를 서버로 보내는 다른 작업이 완료되었을 때 코드에 의해 트리거 되는 작업이라 할 수 있는 것이다.

useHistory

  • 이때 사용하는것이 RRD의 useHistory이다. useHistory는 history 객체에 접속하게 하고, history 객체는 URL을 바꿀 수 있게 해준다.

  • 대표적으로 replace와 push 메서드가 있으며

  • push 메소드를 사용하여 탐색이 가능하므로, 페이지 기록에 새 페이지가 표시된다

  • 또는 현재 페이지를 대체하는 replace 메소드로 탐색할 수도 있다

  • 차이점은 푸시를 사용하면 백(back) 버튼을 사용하여 원래 페이지로 돌아갈 수 있고
    replace 버튼을 사용하면 그럴 수 없다는 점이다

const NewQuotes = () => {
    const history = useHistory();
    const addQuoteHandler=quoteData=>{
        console.log(quoteData);
        history.push("/quotes");
    }
    return (<QuoteForm onAddQuote={addQuoteHandler}/>);
}
  • 즉, replace는 발생한 페이지를 변경하는 redirection과 같고 push는 새 페이지를 추가하는 것이라 볼 수 있다

useLocation

  • useLocation은 location 객체에 접속하게 하고, location 객체엔 최근 로드된 페이지와 URL에 대한 정보가 있다.

<prompt>

  • 가끔 사용자가 form에서 잘 못 눌러 뒤로가기를 누른다면 모든 기록이 사라져버린다. 이를 RRD의 Prompt 컴포넌트가 막아줄 수 있는데
    우선 1. 사용자가 form에 onFocus를 하는지 알아야하고 2. 사용자가 떠나려고 할 때 경고를 해주어야한다.
<Prompt when={state생성해서관리} message={(location)=>"ㄹㅇ 나갈꺼임? data 나갈라감"}/>
  • 이때 문제가 발생하는데 form에서 submit을 누를때 당연하게도 페이지 전환이 있기 때문에 이때도 alert을 뿜어낸다. 그래서
    buttom sumbit단에 onClick handler를 만들어서 관리해주는 것이 좋다.

  • 이때 왜 form 태그에서 submit props에서 관리를 하지 않냐면 한틱이 느리기 때문이다.
    이것을 확인하려면 블럭함수 단위로 state를 차근차근 계산해가면 된다.
    그래서 form이전인 button단계에서 미리 바꾸어주어야한다.

query parameter (query string)

  • query parameter와 route의 path의 다른점은 필수조건이냐 아니냐의 차이이다.
    query parameter는 route 매칭에 전혀 관련이 없지만
    route의 path로 들어가있는 녀석은 필수이다.
  1. 어떠한 event로 URL값을 변경해준다.
history.push("/quotes?키="+"벨류");
  1. URLSearchParams 기본 브라우저 객체를 만들기
    얘가 매개변수로 받는 값을 key, value로 나누어 준다. 따라서 query string에서 편리하게 값을 뽑아낼 수 있다.
const queryParams = new URLSearchParams(location.search);
  1. 뽑아낸 key, value를 바탕으로 코드를 맞춰간다. (오름, 내림차순)
const history = useHistory();
const location = useLocation();
const queryParams = new URLSearchParams(location.search);

const isSoringAscend = queryParams.get("sort") === "asc";

const sortedQuotes = sortQuotes(props.quotes, isSoringAscend);

const changeSortHandler = () => {
  history.push("/quotes?sort="+(isSoringAscend ? "desc" : "asc"));
}

return(
  <Fragment>
        <div className={classes.sorting}>
            <button onClick={changeSortHandler}>{isSoringAscend ? "내림차순":"오름차순"}</button>
        </div>
      <ul className={classes.list}>
        {sortedQuotes.map((quote) => (
          <QuoteItem
            key={quote.id}
            id={quote.id}
            author={quote.author}
            text={quote.text}
          />
        ))}
      </ul>
    </Fragment>
)

nested route 응용

  • nested route는 앞서 말했 던 것 처럼 url의 startwith에 따라서 내부 컴포넌트를 로드해준다고 하였다.
    이를 응용하여 url에 따라 마치 조건문 처럼 사용할 수 있다.
    굳이 귀찮게 new URLSearchParams(location.search); 같은 걸 해서 값을 가져와서 query를 짜지 않아도 된다.

    예제 코드

<Route path={`/quotes/${params.quoteId}`} exact>
  <div className={"centered"}>
  	<Link className="btn--flat" to={`/quotes/${params.quoteId}/comments`}>Load Comments</Link>
  </div>
</Route>

<useRouteMatch>

  • 만약 당신이 URL값이 마음에 안 들어서 바꾸겠다고 결심했다 하자 그렇다면 그동안 작성해온 모든 Route의 path와 Link의 to property를 바꾸어 주어야하는 수고가 있는데 <useRouteMatch\>이 훅은 이러한 수고를 덜어준다.

  • 이때 loaction과 다른 것은 현재 로드 라우트에 관한 정보가 필요하다.
    즉, URL뿐만 아니라 리액트 라우터가 알고 있는 내부에서 관리되는 데이터이다.

  • 하지만 차이점은 URL에 있는 진짜 경로가 아니라 리액트 라우터가 정의한 경로가 들어있고 플레이스홀더, params, 실제 URL도 있다.

  • 따라서 soild하게 일일이 써주는 것 보단 <useRouteMatch\>를 사용하는 것이 추후 유지보수에도 용이하다.

<Route path={`/quotes/${params.quoteId}`} exact />

<Route path={`${match.path}/comments`} />
history.push("/quotes?sort="+(isSoringAscend ? "desc" : "asc"));

history.push(`${location.pathname}?sort=${(isSoringAscend ? "desc" : "asc")}`);

history.push({
  pathname:location.pathname,
  search: `?sort=${(isSoringAscend ? "desc" : "asc")}`,
});
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글