리액트 라우터를 사용하려면 반드시 라우터라는 컴포넌트가 필요하다.
나는 그 중에서 BrowserRouter를 사용했다.
이 컴포넌트를 최상위 컴포넌트에서 감싸주면 모든곳에서 사용할 수 있다.
import {BrowserRouter} from 'react-router-dom';
function App() {
return <BrowserRouter>
...
</BrowserRouter>
}
Routes컴포넌트 안에다가 Route컴포넌트를 배치해서 각 페이지를 나누어줄 수 있다. Routes안에서는 위에서부터 차례대로 Route를 검사한다. 이때 현재 경로와 path 프롭이 일치하는 Route를 찾는 방식이다.
<Routes>
<Route path='/' element={<HomePage />} />
<Route path='posts' element={<PostListPage />} />
<Route path='posts/1' element={<PostPage />} />
</Routes>
리액트 라우터에서는 <a>태그 대신에 Link라는 컴포넌트를 대신 사용한다. to라는 prop으로 이동할 경로를 정해주면 된다.
<Link to="/posts">블로그</Link>
Route컴포넌트안에다가 Route컴포넌트를 배치하면 하위페이지를 나눌 수 있다. 이때 하위 페이지에서 최상위 경로에 해당하는 경로는 path프롭이 아니라, index라는 이름의 prop을 사용하면 된다.
<Routes>
<Route path='/' element={<HomePage />}/>
<Route path='posts'>
<Route index element={<PostListPage />}
<Route path='1' element={<PostPage />}
</Route>
</Routes>
콜론 (:)으로 시작하는 문자열을 사용하면, 경로에 파라미터를 지정할 수 있다. 예를들어, 아래처럼 /posts/:postId 라는 경로는 /posts/123 이라던지, /posts/abc 라는 주소로 접속하면 123이나 abc라는 값을 postId라는 파라미터로 받는다.
<Routes>
<Route path='/' element={<HomePage />} />
<Route path='posts'>
<Route index element={<PostListPage />} />
<Route path=':postId' element={<PostPage />} />
</Route>
</Routes>
여기서 이 경로파라미터를 사용하려면 useParams라는 훅을 사용하면 된다.
function PostPage() {
const {postId} = useParams();
...
}
useSearchParams라는 Custom hook으로 SearchParams 객체를 받아올 수 있다. 이 hook은 SearchParams객체와 Setter함수를 배열형으로 리턴한다. 이때 쿼리값은 SearchParams의 get함수로 가져온다.
import {useSearchParams} from 'react-router-dom';
function PostListPage() {
const [searchParams, setSearchParams] = useSearchParams();
const filterQuery = searchParams.get('filter');
}
만약 쿼리값을 변경하고 주소를 이동하고 싶다면, Setter함수에 객체를 넘겨주면 된다. 이때 객체의 프로퍼티로 쿼리값을 지정할 수 있다. 아래 예시는 ?filter=react라는 쿼리로 이동하는 예시이다.
setSearchParams({
filter : 'react'
});
검색기능에 자주 쓰일 수 있다.
const [searchString, setSearchString] = useState();
const [searchParams, setSearchParams] = useSearchParams();
// 이전에 포스트 리스트를 postList로 받아왔다는 가정
const filterPostList = postList.filter((itme) => {
const filterQuery = searchParams.get('filter') || '';
return item.postTitle.toLowerCase().includes(filterQuery.toLowerCase());
});
const inputSearchString = (e) => {
setSearchString(e.target.value);
}
const onClcikHandler = () => {
setSearchParams({filter : searchString});
}
// 이제 filtering한 filterPostList를 prop으로 내려주면 된다.
리액트 라우터는 리액트에서 제공하는 기본 기능이 아니기 때문에, react-router-dom이라고 따로 설치를 해주어야 한다.
<NavLink
to='/about'
activeStyle={{
fontWeight : 'bold',
color : 'red',
}}
>
About...
</NavLink>
NavLink 컴포넌트는 style속성으로 함수를 줄 수 있는데, 자동으로 isActive 프롭을 제공한다. NavLink는 현재 활성화된 경로인지 판단하고, 이에 따라 몇가지 props를 함수로 전달한다.
isActive는 현재 경로가 NavLink의 to속성과 일치하면 true, 그렇지않으면 false를 리턴한다.
isActive : 현재 경로가 활성화 된 상태인지의 여부
isPending : 라우트가 대기중일때 true
이에 따라 동적으로 클래스 추가가 가능하다.
const Navigation = () => {
const isThisActive = ({ isActive }) => {
return isActive
? {fontWeight: 'bold', textDecoration:'underline'}
: {color : 'black', textDecoration: 'none'};
};
return (
...
<NavLink to='/' style={isThisActive}>
Home...
</NavLink>
...
)
}
Navigate 컴포넌트를 사용한다.
리턴값으로 Navigate컴포넌트를 리턴하면 to 프롭으로 지정한 경로로 이동하게 된다.
function PostPage() {
//...
const post = getPost(postId);
//post가 없는경우 /posts페이지로 디오
if(!post) {
return <Navigate to='/posts' />;
}
}
const navigate = useNavigate();
const handleClick = () => {
// 어떤 작업을 한 다음 페이지를 이동
navigate('/wishlist');
}
세가지 모두 페이지를 이동할 때 쓸 수 있다는 점에서 비슷하다.
Link : 사용자가 클릭해서 페이지를 이동할 때
Navigate : 특정 경로에서 렌더링 시점에 다른 페이지로 이동시키고 싶을때 사용
예 : 쇼핑몰의 회원전용 페이지에 로그인없이 들어와서 로그인페이지로 리다이렉트 하는경우
useNavigate : 특정한 코드의 실행이 끝나고 나서 페이지를 이동시키고 싶을때 사용.
예 : 쇼핑몰에서 장바구니 담기를 눌렀을때 리퀘스트를 보내고 장바구니 페이지로 이동시키는 경우
특징 : 웹사이트를 보려면 초반에 작업하는 시간이 필요해서 처음 화면이 뜨는게 조금 느릴 수 있다. 하지만 만들고 나면 잘 동작한다.
특징 : 빠르게 화면을 볼 수 있어서 좋고, 검색엔진에서도 점수를 잘 받아서 사람들이 내 웹사이트를 더 쉽게 찾을 수 있다.
특징 : 서버가 할일이 줄어들어 빠르지만, HTML을 바꾸고 싶으면 새로 만들어서 배포해야한다.
요약 :
클라이언트 사이드 렌더링 : 브라우저에서 HTML을 만듦
서버 사이드 렌더링 : 서버에서 HTML을 만들어 보냄
정적 사이트 생성 : 미리 만들어둔 HTML파일을 보여줌
*Next.js를 사용하면 이 모든것을 쉽게 할 수 있다.