React-Router(2): router에게 props전달

hyunn·2021년 9월 11일
0

리액트 [Movie App]

목록 보기
9/10

Router Props

browser와 react app의 router를 연결하게 되면 각각의 해당 Route(태그)와 연결된 컴포넌트에 props로 match, location, history객체를 전달한다.

Link "to"에 string말고 object를 이용하여 props에 특정 요소를 추가로 넣어줄 수도 있다.

<Link to={{
      pathname:`/movie/${id}`,
      state:{year,title,summary,poster,genres}
    }}>
...
</Link>

Match

<Route path>와 url이 matching된 정보가 담겨져있다. 대표적으로 match.params로 path에 설정한 파라미터값을 가져올 수 있다.

· path : [string] 라우터에 정의된 path

· url : [string] 실제 클라이언트로부터 요청된 url path

· isExact : [boolean] true일 경우 전체 경로가 완전히 매칭될 경우에만 요청을 수행

· params : [JSON object] url path로 전달된 파라미터 객체

Location

location객체에는 현재 page의 정보를 가지고 있다. 대표적으로 location.search로 현재 url의 query string을 가져올 수 있다.

· pathname : [string] 현재 페이지의 경로명

· search : [string] 현재 페이지의 query string

· hash : [string] 현재 페이지의 hash

History

history객체는 browser의 history와 비슷하다. 스택(stack)에서 현재까지 이동한 url 경로들이 담겨있는 형태로, 주소를 임의로 변경하거나 되돌아갈 수 있도록 해준다.

· length : [number] 전체 history 스택의 길이

· action : [string] 최근에 수행된 action (PUSH, REPLACE or POP)

· location : [JSON object] 최근 경로 정보

· push(path, [state]) : [function] 새로운 경로를 history 스택으로 푸시하여 페이지를 이동

· replace(path, [state]) : [function] 최근 경로를 history 스택에서 교체하여 페이지를 이동

· go(n) : [function] : history 스택의 포인터를 n번째로 이동

· goBack() : [function] 이전 페이지로 이동

· goForward() : [function] 앞 페이지로 이동

· block(prompt) : [function] history 스택의 PUSH/POP 동작을 제어

참고: gongbu-ing.tistory

영화를 클릭했을 때, Link가 지정 path로 이동하면서 browser와 router가 연결되고, Route(태그)에게 정보(props)를 보낸다.

//Movie.js
...
function Movie({id, year, title, summary, poster,genres}){
  return(
    <div className="movie">
     <Link to={{
      pathname:`/movie/${id}`,
      state:{
        year,
        title,
        summary,
        poster,
        genres
      }
    }}>
      <img src={poster} alt=""/>
      <div className="movie_data">
        <h3 className="movie_titile">{title}</h3>
        <h5 className="movie_year">{year}</h5>
        <ul className="movie_genres">{genres.map((genre, index) => {if(index > 3){return;} return <li key={index}className="genres_genre">{genre}</li>})}</ul>
        <p className="movie_summary">{summary.slice(0,180)}...</p>
      </div>
     </Link>
    </div>
    //function component도 retrun할때 하나의 tag로 감싸야 함
  )
} 

(Movie.js에서 구현한) 영화를 클릭하여 Link가 지정 path로 이동하고 동시에 정보(props)를 넘겨주면, 같은 path를 가지고 있는 router가 자신의 component를 구현할때 정보(props)를 받아 이용할 수 있다.
router(Route태그)는 browser가 지정 path로 이동했을 때(Link의 역할), 지정된 component를 구현한다.

///App.js
...
function App(){
  return(
    <HashRouter>
      <Navigation />
    
      <Route path="/" exact={true} component={Home} />
      <Route path="/about" component={About} />
      <Route path="/movie/:id" component={Detail} />
    </HashRouter>
    )
}
//Detail.js
//해당 component가 정보(props)를 사용할 수 있다.
...
class Detail extends React.Component{
  componentDidMount(){
    console.log("componentDidMount");
    const { location, history } = this.props;
    if(location.state === undefined){
      history.push("/");//다시 home으로 돌아가게 함
    }
  }
  render(){
    console.log("render");
    const {location} = this.props;
    if(location.state){
      return <span>{location.state.title}</span>;
    }
    else {//state값이 없을 때
      return null;//아무것도 구현되지 않고(error가 발생 안하도록), componentDidMount가 실행되어 다시 home화면으로 돌아간다.
    }
  }
}

props객체안에 여러 값들이 있는데(history, location, match 등...), state는 location객체안에 있다.

history객체를 이용하면 다른 url로 이동할 수 있는 기능(push)이 있다. 따라서 영화를 클릭하지 않고 다이렉트로 주소에 접근하면 다시 홈화면으로 돌아가게 구현했다.

하지만 render가 componentDidMount보다 먼저 실행되기 때문에 다이렉트로 접근했을 때 render에서 state값을 참조하면 error가 발생한다. 이를 방지하기 위해 render에서도 state값이 존재하는지 판별하였다.

[Link컴포넌트 때문에 CSS가 깨질 때]
Link컴포넌트는 리액트에서 ReactDOM에 의해 a태그로 변환되서 보여진다.
display: contents -> container를 사라지게하여 DOM에서 다음 단계의 하위 요소를 생성한다.

.movies a{
display: contents;
text-decoration: none;
}
profile
오늘보다 더 나은 내일

0개의 댓글