React Router dom v6
React Router dom의 custom hook
useLocation
useParams : 다이나믹라우트 정보
useNavigate : 페이지 이동
useLocation : 페이지정보
pathname은 현재위치
search는 쿼리문 부분이다
대충 위와같은 느낌이다.
그래서 useLocation은 현재 페이지 정보를 알 수 이는 함수이다.
이걸 가지고 우린 두가지를 해볼 수 있다.
1. topNav가 Main 페이지에서 안보이게 만들어보자
TopNav의 Link만 쓰던것을 우리가 만든 컴포넌트로 바꾸자
이제 리액트가 익숙해지면 아래와 같이도 구현할 수 있다.
이제 책의 isbn을 기준으로 책별 페이지를 만들어보자.
데이터를 보면 isbn은 위와같이 온다 우리는 두번째것을 사용하자
BookList.jsx에다가 Link를 걸었다. 이렇게 그때그때마다 페이지를 따로 생성해주는 것을 dynamic routing이라고 부른다.
Router.js 에 :isbn을 추가해주었다. 이것을 useParams를 통해서 데이터 접근이 가능해진다. 이건 BookDetail 컴포넌트로 가도록 만들자.
---
중복제거
시작하기전에 보니까 여기에서 headers가 반복되는 것을 확인할 수 있다. axios를 외부로 빼주는 작업부터해보자
api/index.js를 만들어서 axios의 instance를 사용해보자
https://developers.naver.com/docs/serviceapi/search/book/book.md#%EC%B1%85
책 - Search API
책 NAVER Developers - 검색 API 책 검색 개발가이드 검색 > 책 네이버 책 검색 결과를 출력해주는 REST API입니다. 비로그인 오픈 API이므로 GET으로 호출할 때 HTTP Header에 애플리케이션 등록 시 발급받은 C
developers.naver.com
가보면 우리가 얻어와야하는 값이 있다. 그걸 처리하자
위와같이 getBookDetail 함수를 새롭게 제작해서 데이터를 받아오도록 해보자
내용이 잘뜨는 것을 확인할 수 있다.
import { useCallback, useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import styled from "styled-components";
import { getBookDetail } from "../../apis/book";
const BookDetail = () => {
const [book, setBook] = useState({});
const { isbn } = useParams();
const {
image,
title,
author,
publisher,
price,
discount,
pubdate,
description,
} = book;
const searchBookDetail = useCallback(async () => {
const params = {
d_isbn: isbn,
};
const { items } = await getBookDetail(params);
setBook(items[0]);
console.log(items);
console.log(items[0]);
}, [isbn]);
useEffect(() => {
searchBookDetail();
}, [isbn, searchBookDetail]);
return (
<>
<Image src={image} />
<Title>{title}</Title>
<Author>{author}</Author>
<Publisher>{publisher}</Publisher>
<Price>
가격: {(+price).toLocaleString()} / {(+discount).toLocaleString()}
</Price>
<PubDate>출간일: {pubdate}</PubDate>
<Description>{description}</Description>
</>
);
};
const Image = styled.img`
margin: 5% auto;
height: 200px;
`;
const Title = styled.h2``;
const Author = styled.h4``;
const Publisher = styled.h4``;
const PubDate = styled.p``;
const Price = styled.h5``;
const Description = styled.h5`
font-weight: normal;
`;
export default BookDetail;
여기에서부터 코드를 구현해나가자
useCallback을 사용했는데 랜더링 될때마다가 아닌 특정상황에서만 함수를 새로 선언하고 싶을 떄 사용함으로 성능의 향상을 이끌어내는 방법이다.
만약 이걸 useCallback으로 감싸지 않으면 위와같이 계속 함수가 실행되며 렌더링된다. 그리고 이때 계속 실행되는 이유는 함수가 그냥 선언되었으니 setBook을 품고 있어서 items가 계속 다시 선언되어서 그렇다.
그런데 지금 문제점은 검색하고 -> 상세페이지 -> 되돌아가기
하면 원래보던 페이지가 업어져 있다.
이게 바뀌지 않기 위해서는 그 정보를 query string을 계속 남겨놓았기 때문이다. 그래서 우리도 검색창의 쿼리스트링을 바꾸는 것만으로도 검색결과를 쉽게 바뀔 수 있도록 만들어보자.
1. 검색을하면 URL 쿼리스트링에 검색어정보 담아서 이동
2. 브라우저에서 쿼리스트링에 검색어정보가 있는 경우
1) input에 검색어를 넣고
2) 검색결과를 출력한다.
이를 위해서 useNavigate를 사용해야한다.
위와같이 useNavigate를 받을 변수와 해당 변수를 가지고 이동할 속성값을 넣어주어서 처리해줄 수 있다. 여기에서 pathname은 구지 않들어가도 될거 같다. 일단 가시성을 위해 넣어놓자
이동시 위와같이 검색창이 붙는 것을 확인할 수 있다.
이런식으로 보다 깔끔하게 만들어줄 수 있다.
위와같이 하면 query string을 붙일수는 있지만 query라는 속성말고도 따른 url 파라미터를 붙여야 하는데 위와같이하면 불편하다 그래서 라이브러리의 도움을 받아보자.
qs 라이브러리를 사용해보자. qs 라이브러리는 두가지 기능이 있다. 첫번째는 query string이 왔을때 qs를 쓰면 객체로 만들어준다. 또 하나는 객체를 query string으로 바꾸어준다.
그래서 위와같이 구현하면 우리가 귀찮게 ?query 안해주어도 query string을 자동으로 만들어준다.
이제두번째로 원래페이지로 돌아왔을때의 쿼리정보가 있게끔 만들어 검색결과가 나오게끔 해야한다.
Book 컴포넌트 안에 현재의 위치를 저장할 search를 받아오고 이걸 가져다가 파싱을 해서 처리해야 한다. 다시금 qs문법을 사용해서 useEffect 내부에서 처리하도록 만들자
해서 따와보니 위와같이 쿼리값이 잘 분리되어 나온다. 이걸 가지고 query변수에 넣어주자
결론은 위와같이 search에 따라서 query랑 text 모두 바뀌게 된다.
이렇게 나온것을 가지고 검색결과 정보를 하위 컴포넌트에 넘겨주자.
1. useEffect로 page 값이 바뀔 때마다 url에 page 정보를 넣는다. : 새로운 useState
2. 쿼리스트링에서 page 정보를 추출하여 setPage 함수로 page값을 변경한다. : search의 useState 부분에서 처리
const Book = () => {
const { search } = useLocation();
const navigate = useNavigate();
const [text, settext] = useState("");
const [bookList, setBookList] = useState([]);
const [country, setCountry] = useState(countryList[0].code);
const [query, setQuery] = useState("");
const [total, setTotle] = useState(0);
const [page, setPage] = useState(1);
useEffect(() => {
const { query, page } = qs.parse(search.slice(1));
if (query) {
setQuery(query);
settext(query);
}
if (page) {
setPage(+page); //이렇게하면 숫자로 바뀜
}
}, [search]);
useEffect(() => {
searchBook();
}, [country, page, query]);
const handleSubmit = (e) => {
e.preventDefault();
setPage(1);
setQuery(text);
};
const searchBook = async () => {
if (!query) return;
const start = page * 10 - 9;
const params = { query, start };
if (country !== "ALL") {
params.country = country;
}
const { items, total } = await getBookList(params);
setBookList(items);
setTotle(total);
const search = qs.stringify({ query, page });
navigate({ search });
};
'Development(Web, Server, Cloud) > 22) React.js & Node.js' 카테고리의 다른 글
REACT : Naver API를 활용한 사이트 만들기 (0) | 2022.01.20 |
---|---|
React.js & Node.js 16일차 : 네이버API 서버구현하기 + 인스타 골격, URL, URI (0) | 2022.01.18 |
React.js & Node.js 14일차 : 영화./책 검색사이트 (0) | 2022.01.12 |
React.js & Node.js 13일차 : 영화/책 검색 사이트, CORS Problem, Axios(API), Pagination (0) | 2022.01.11 |
React.js & Node.js 12 : 영화/책 검색 사이트, React Router, Atomic Design Pattern (0) | 2022.01.10 |