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>
<Route path>
와 url이 matching된 정보가 담겨져있다. 대표적으로 match.params로 path에 설정한 파라미터값을 가져올 수 있다.
· path : [string] 라우터에 정의된 path
· url : [string] 실제 클라이언트로부터 요청된 url path
· isExact : [boolean] true일 경우 전체 경로가 완전히 매칭될 경우에만 요청을 수행
· params : [JSON object] url path로 전달된 파라미터 객체
location객체에는 현재 page의 정보를 가지고 있다. 대표적으로 location.search로 현재 url의 query string을 가져올 수 있다.
· pathname : [string] 현재 페이지의 경로명
· search : [string] 현재 페이지의 query string
· hash : [string] 현재 페이지의 hash
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 동작을 제어
영화를 클릭했을 때, 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;
}