리액트의 외부 라이브러리 중 하나.
항상 라이브러리를 설치함에 있어서 주의해야 할 점은
필요와 목적을 고민하고 그에 부합하는 라이브러리를 사용해야 한다는 점과
사용법을 외우기 보다는 유용하게 사용하는 방법을 찾는 법을 아는 것이 중요하다고 할 수 있겠다.
언제나처럼 npm install 부터 시작
npm install react-router-dom@6
기본적으로 해주어야 할 셋팅이 있는데
index.js 파일로 가서
import { BrowserRouter } from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
을 BrowserRouter 컴포넌트로 감싸주어야 한다.
ReactRouter 를 쓰는 방법은 2 단계로 나눌 수 있는데,
우선 첫번째,
<Routes>
<Route path='/도메인' element={ 해당 페이지에서 보여줄 컴포넌트 }/>
</Routes>
Routes 컴포넌트 안에 Route 컴포넌트를 집어넣고
path 속성으로는 도메인을,
element 속성으로는 해당 도메인에 접속하면 보여줄 페이지를 설계하면 된다.
path 에 ‘/’ 를 작성하면 기본 페이지를 의미한다.
그리고 두번째,
<Link to='/도메인'> 링크 </Link>
링크 태그로 해당 도메인으로 이동하는 링크를 달아주면 된다.
그런데 Link 태그는 커스텀에 다소 손이 많이가기 때문에,
let navigate = useNavigate();
return (
<button onclick={()=>{
navigate('/도메인')
}}>해당 도메인으로 이동하는 버튼</button>
)
useNavigate 함수를 이용해 링크를 걸어주는게 일반적인 설계방법이다.
useNavigate 함수의 파라미터로 정수를 입력하면 앞으로 혹은 뒤로가기 버튼을 손쉽게 구현할 수 있다.
예를들어,
1은 앞으로 1페이지, -1은 뒤로 1페이지 같은 기능이다.
주의사항
유저의 오입력으로 잘못된 도메인으로 접속했을 경우에 대한 처리방법.
오입력에 대한 예외처리를 해주지 않으면 아무 컴포넌트도 보여주지 않기때문에 곤란하다.
그럴때를 대비해 404페이지 를 설정해준다.
404 페이지는 ‘미리 예상된 오류에 대한 의도된 처리’ 라는 점.
다시 말해 404 페이지를 설계하는 것도 개발자의 역량이라는 것.
심지어 도메인을 잘못 입력하는 오류는 아주 빈번하게 발생하기에
이에 대한 설계를 고민하는 것도 정말 중요한 일이 아닐 수 없다.
404 페이지는
<Route path='*' element={ 설정해놓지 않은 도메인으로 접속했을 경우 보여줄 컴포넌트 }/>
이런식으로 만들 수 있다.
scss 를 공부할 때 가장 편했던 부분이 Nesting 에 관한 부분이었는데
ReactRouter도 마찬가지로 도메인의 하위 경로를 설정하는 방법이다.
예를들어,
react-bootstrap 의 공식 홈페이지의
Components 탭의 하위 항목들을 보자.
<Route path='/Components/Alerts' element={ <div>Alerts ~~~</div>}/>
<Route path='/Components/Badge' element={ <div>Badge ~~~</div>}/>
이런식으로 설계할 수 있는 라우터를
<Route path='/Components' element={<Components>}>
<Route path='Alerts' element={<Alerts>}/>
<Route path='Badge' element={<Badge>}/>
</Route>
이런식으로 설계할 수 있다는 것이다.
해당 기능의 가장 큰 장점은
유사한 서브페이지들이 많이 필요할 때 일부분만 바꾸어 보여줄 수 있다는 점에 있다.
ReactRouter 의 outlet 컴포넌트로
상위 도메인에서 하위도메인의 네스팅 위치를 정해줄 수 있다.
function Components(){
return(
<div>
<Outlet>요기</Outlet>
</div>
)
}
<Route path='/path/:작명'></Route>
url파라미터를 이용해 페이지를 여러개 만드는 방법도 있다.
위 의 /: 키워드를 사용하면
path 컴포넌트에서
function path(){
let {params} = useParams();
return(
)
}
useParams()로 path 도메인 이후의 url 를 파라미터로 가져올 수 있다.
예를들어
path/1 도메인으로 접속하면 params 변수에 1 이라는 값이,
path/title 도메인으로 접속하면 params 변수에 ‘title’ 이라는 값이 저장된다.
출처 - 코딩애플
import { useParams } from "react-router-dom";
function Detail(props) {
let { id } = useParams();
return id < props.product.length ? (
props.product[id].id == id ? (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={props.product[id].src} width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{props.product[id].title}</h4>
<p>{props.product[id].content}</p>
<p>{props.product[id].price} $</p>
<button className="btn btn-danger">Order</button>
</div>
</div>
</div>
) : (
<></>
)
) : (
<>404페이지</>
);
}
export default Detail;
해당 제품의 고유 id 도메인으로 접속하면 자세한 정보를 출력해주는 컴포넌트를 만들었다.
정답에는 array.find 메소드를 사용해서
let { id } = useParams();
let findId = props.product.find(function(x){
return x.id == id;
})
findId 변수로 해당 제품을 찾는 식으로 코딩을 하셨는데,
이러한 경우에
예를들어 detail/3 이나 다른 도메인으로 접속했을 경우
Uncaught TypeError: Cannot read properties of undefined (reading 'src')
이런식으로 undefined 에러가 발생했다.
어떤식으로 오류처리를 해줄까 고민하다가
id가 제품 넘버링 이라면 db의 데이터 갯수보다 적을 경우에만 도메인 표시를 해주고
그렇지 않을 경우 404 페이지를 출력하는 방식을 생각해냈다.
정답 스타일로 코드를 고쳐본다면
function Detail(props) {
let { id } = useParams();
let findId = props.product.find(function (e) {
return e.id == id;
});
return id < props.product.length ? (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src={findId.src} width="100%" />
</div>
<div className="col-md-6">
<h4 className="pt-5">{findId.title}</h4>
<p>{findId.content}</p>
<p>{findId.price} $</p>
<button className="btn btn-danger">Order</button>
</div>
</div>
</div>
) : (
<>404페이지</>
);
}
이런식으로 고칠 수 있다.
옳게 된 코딩인지는 솔직하게 잘 모르겠다.
예상되는 문제라고 한다면..
우선 db의 id가 제품의 넘버링이 아닌 랜덤으로 생성된 번호라면 이러한 방식을 사용할 수 없다.
id를 파라미터로 쓰는 이유는 정렬이나 상품의 순서가 바뀌었을 때 식별하기 위함인데
넘버링이 아니라면 db상의 제품의 갯수와 id간의 상관관계가 없으므로 이러한 오류처리를 해줄 수 없다.
해결방법을 찾아봐도 잘 모르겠어서 이 부분은 추가로 학습이 필요할 것 같다.
npm start styled-components
자바스크립트 파일 안에서 style 을 좀더 쉽게 지정할 수 있다.
let YelloBtn = styled.button`
background : yellow;
color : black;
`
하나의 스타일이 적용된 컴포넌트를 만드는 느낌.
css파일을 열지 않아도 되서 편리하다.
스타일이 다른 서로 다른 파일을 간섭하지 않으므로 각각의 스타일을 지정하는데 유리하다.
컴포넌트.module.css 로 파일 이름을 네이밍 하는 것으로도 방지오염이 가능하다.
let YelloBtn = styled.button`
background : ${props => props.bg};
color : black;
`
<YellowBtn bg='blue'/>
파라미터 문법도 사용할 수 있기때문에 유사한 속성을 가진 서로다른 기능도 구현할 수 있고,
let NewBtn = styled.button(YellowBtn)`
color = ${ props => props.bg == 'blue' ? 'white' : 'black' };
`
자바스크립트를 적용하기 때문에 조건문도 활용할 수 있다.
컴포넌트도 생명주기가 있다.
컴포넌트가 보이는 순간 - 페이지에 장착되는 순간 (mount)
컴포넌트가 업데이트 되는 순간 (update)
컴포넌트가 필요가 없어 제거되는 순간 (unmount)
이 생명주기에 간섭이 가능하다.
예를들어, 마운트 되는 순간에 어떤 기능을 추가한다던지
업데이트가 되는 순간 어떤 기능을 추가한다던지 할 수 있다.
useEffect(()⇒{
mount, update 시 실행될 코드
})
useEffect hook 의 실행 시점이 가장 중요한데, html 렌더링 후에 동작한다.
html 을 보여주고 나서, 그림을 그린 이후에 연산을 하기 때문에
사용자 입장에서 로딩속도가 빠르다고 느껴지게 할 수 있다.
따라서 시간이 오래걸리는 어려운 연산, 서버에서 데이터를 가져오는 ajax 요청,
타이머 같은 작업은 useEffect hook 을 사용하는게 일반적이다.
여담으로 함수의 핵심기능 외의 부가기능을 side effect 라고 하는데 거기서 따왔다고 한다.
useEffect에 넣을 수 있는 옵션으로 다양한 코딩을 할 수 있는데,
useEffect(()=>{}, [State])
훅의 두번째 파라미터로 [] 중괄호를 넣을 수 있는데 그 안에 변수나 state 를 넣으면
해당 state 가 변경되었을 때 useEffect 내부의 코드를 실행해 주도록 할 수 있다.
아무것도 넣지 않으면 mount 시 1회만 실행해준다.
useEffect 내부 코드를 실행하기 이전에 특정 코드를 실행하고 싶으면
useEffect(()=>{
return ()=>{
clean up function
}
})
return 내부에 콜백함수 형식으로 코드를 작성하면 된다.
clean up function 이라고도 하는데,
예를들어, 기존의 타이머를 제거하고 새 타이머를 실행한다던가,
기존의 ajax 요청을 취소하고 새로 요청을 보낸다던가 하는 기능을 구현할 수 있다.
useEffect hook 내부의 코드는 mount시 항상 실행되므로
기존의 함수가 실행되기도 전에, 서버로 보낸 요청에 대한 답을 받기도 전에
재 mount, 재렌더링이 되어버린다면 버그를 초래할 수 있기 때문이다.