상세 컨텐츠

본문 제목

[react history] history.push()시 url은 변경되는데 화면은 안바뀔 때... 중첩라우팅 시 내가 한 실수 기록

React, Node.js, Express

by Jjiveloper 2021. 5. 4. 21:25

본문

728x90

상황

- 후기 글 작성 시 로그인 된 사람만 작성 페이지로 들어갈 수 있다.

- 로그인 되지 않은 사람이 페이지 접속 시 로그인 화면으로 이동시킨다.

- 이때 history.push를 이용한다.

 


src>app.js

import 'bootstrap/dist/css/bootstrap.min.css';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';

/**********Route import**********/
import Customer from './router/customerRouter';
import Main from "./components/product/productMain";
import Board from "./router/boardRouter";
import Order from "./router/orderRouter";
import Product from "./router/productRouter";
import Management from "./components/management/management";
import NavBar from "./components/home/navBar";

function App(){

    return(
        <div className="App">
            <Router>
                <NavBar/>
                <Switch>
                    <Route exact path="/" component={Main}/>
                    <Route path="/product" component={Product}/>
                    <Route path="/customer" component={Customer} />
                    <Route path="/board" component={Board} />
                    <Route path="/order" component={Order} />
                    <Route path="/management" component={Management} />
                </Switch>
            </Router>
        </div>
    );
}

export default App;

최상단 app에서 Switch를 이용해 중첩 라우팅을 했다.

customer: 고객 로그인/로그아웃/회원가입 관련, board: 후기글,문의글 관련 등...

지금 볼 것은 후기글작성 시 로그인 안된 사람 걸러내고 로그인 페이지로 이동시키기이다,


src>router>boardRouter.js

import React from "react"
import {BrowserRouter as Router, Link, Route, Switch} from "react-router-dom"
import Inquiry from "../components/board/inquiry";
import Review from "../components/board/review";
import BoardList from "../components/board/boardList";
import InquiryList from "../components/board/inquiryList";
import ReviewList from "../components/board/reviewList";

function Board({ match }) {

    return (
        <Router>
            <header>
                <Link to={`${match.path}/review`}>
                    <button>후기작성</button>
                </Link>
                <Link to={`${match.path}/inquiry`}>
                    <button>문의작성</button>
                </Link>
                <Link to={`${match.path}/reviewList`}>
                    <button>후기글 보기</button>
                </Link>
                <Link to={`${match.path}/inquiryList`}>
                    <button>문의글 보기</button>
                </Link>
            </header>
            <Switch>
                <Route exact path={`${match.path}/`} component={BoardList} />
                <Route exact path={`${match.path}/review`} component={Review} />
                <Route exact path={`${match.path}/inquiry`} component={Inquiry} />
                <Route exact path={`${match.path}/reviewList`} component={ReviewList} />
                <Route exact path={`${match.path}/inquiryList`} component={InquiryList} />
            </Switch>
        </Router>
    )
}

export default Board;

app.js에서 /board (게시판) 으로 요청온 뒤 또 뒤의 url경로에 따라 바뀔 화면 중첩 routing목록이다.

${match.path} : app.js에서 /board로 통해왔으니 match.path 는 board이다.

/board/review로 가보자


src>component>board>review.js

import {useCallback, useEffect, useState} from "react";
import axios from "axios";

function Review({history}) {

    useCallback(useEffect(()=>{
        let url = '/product/getPcode' ;
        axios.get(url)
            .then(res => {
                if(res.data === 'ppfalse'){
                    alert('로그인이 필요한 서비스입니다.');
                    return history.push('/customer/login');
                }
                setProducts([res.data.row]);
                setUser({...user, cid: res.data.cid, cname: res.data.cname})
                setReview({...review, pCode: res.data.row[0].pcode}); // select 안바꾸면 기본 선택값은 첫번째 pcode...
            })
            .catch(err => console.log(err))
    },[]))
    
// ...생략

    return(
        <div>
            <h1>후기 게시판</h1>
            <form onSubmit={submitForm}>

                상품
                <select name="pCode" value={review.pCode} onChange={onTyping}>
                    {productsList}
                </select>
                <br/>
                제목 <input type="text" name="title"  value={review.title} onChange={onTyping} placeholder="제목을 입력해주세요." /> <br/>
                작성자 {user.cname}님 ({user.cid}) <br/>
                평점 {rate} {review.rating}점 <br/>
                내용 <br/>
                <textarea name="content" value={review.content} onChange={onTyping} id="content" cols="30" rows="10"> </textarea> <br/>
                <button type="submit">작성하기</button>
            </form>
        </div>
    );
}

export default Review;

지금 봐야할 곳은

서버단에서 받아온 데이터가 ppfalse이면 로그인이 되지않은 상태라 history.push를 이용해

/customer/login 경로의 로그인 페이지로 이동시키는 것이다.

 

node.js에서 로그인 판별은 passport 라이브러리를 이용했다... 자세한건 추후에 글 올린 후 링크올릴 예정


로그인되지 않은 상태에서 후기글 작성페이지(/board/review) 접속 시 로그인 되지않았을때 로그인 유효성검사는 제대로 됐다.

url은 제대로 바뀌었는데

로그인 페이지도 보이지 않고

 

후기작성, 문의작성 등 개발 시 편의를 위해 boardRouter에 잠깐 넣어놨던 Link버튼이 그대로 보인다.

history.replace도 써보고 했는데도 계속 이상태라서 잠깐 포기했는데 관련 글들을 찾아보다가 뭔가 찜찜해져서 딱 2군데를 바꿔봤더니 해결되었다......


이것이 최상단의 app.js 라우터이고

동적 라우팅을 위해 만든 하위의 라우터이다... 며칠동안 해결 못했었는데 오늘 갑자기 번뜩였던 것이

<Router>하위에 <Router>를 또 넣어놔서 history.push를 했을때 최상단의 Router에 도달하지 못하고 가로막힌게 아닐까...!

그래서 하위 라우터 컴포넌트의 <Router> 를 지워봤다.

function Board({ match }) {

    return (
        <>
            <header>
                <Link to={`${match.path}/review`}>
                    <button>후기작성</button>
                </Link>
                <Link to={`${match.path}/inquiry`}>
                    <button>문의작성</button>
                </Link>
                <Link to={`${match.path}/reviewList`}>
                    <button>후기글 보기</button>
                </Link>
                <Link to={`${match.path}/inquiryList`}>
                    <button>문의글 보기</button>
                </Link>
            </header>
            <Switch>
                <Route exact path={`${match.path}/`} component={BoardList} />
                <Route exact path={`${match.path}/review`} component={Review} />
                <Route exact path={`${match.path}/inquiry`} component={Inquiry} />
                <Route exact path={`${match.path}/reviewList`} component={ReviewList} />
                <Route exact path={`${match.path}/inquiryList`} component={InquiryList} />
            </Switch>
        </>
    )
}

export default Board;

<Router>를 그냥 <>로 바꿔봤음

 

그랬더니 결과는!!

확인을 누르면?

ㅠㅠㅠ정상적으로 화면이 바뀌었다...

 

저렇게 하위 라우터 컴포넌트를 Router로 감쌌던 이유가 뭔지 생각했었는데

<Route>태그나 <Link> 태그는 BrowserRouter(=Router)태그 안에서만 사용할 수 있다고 에러가 나서

하위 라우터 컴포넌트들도 아무 생각없이 이렇게 Roter로 감쌌더니 이런 참사가 났다...

 

나같은 실수를 하는 분들은 얼마없을 수도 있지만 history에러를 해결하는 방법을 검색해도 이런 실수는 안하셔서 그런가 이런 글이 안나와서....혹시몰라 남긴다

개발 화이팅... 🙃


+) 이건 최근에 한 또 다른 실수!!

history.push 뒤에 쿼리스트링을 넣어줬을 때도 동일한 현상이 일어났었다.

url 뒤에 ?name=어쩌고 이런 파라미터 넣었는데 안되던 분들은 아래 링크 참고하세염

 

https://xively.tistory.com/63

 

[React] history.push 이용해서 query string 보내기 (리액트 페이지 이동 시 url parameter 전달)

내가 반나절 동안 삽질했던 history.push 페이지 이동 시에 url 뒤에 parameter를 넘겨줄 때 한 실수를 적어보고자 한다. 상황) 페이지 이동 시 history에 props를 담아서 전달해주면서 동시에 url 뒤에 query s

xively.tistory.com

 

728x90
반응형

관련글 더보기