잘 안풀렸던 페이지네이션을 정리할겸 티아이엘을 써보자.
쇼핑몰에 업로드할 모든 제품군들을 8개씩으로 분류해 페이지네이션 해주는 상황
일단 JpaRepository에서 타입을 Page로 받아준다.
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findAll(Pageable pageable);
Optional<Product> findById(Long productId);
}
서비스 영역에서 마찬가지로 타입을 Page로 받아주고
sort는 분류를 원하는 타입명(나는 생성일 순으로 하고싶어 createdAt을 넣었다.)을 넣어주고 리턴한다.
그리고 총 페이지수를 잡아줘야하므로 findAll 한 것을 totalPages로 바꿔준다.
@Service
@Transactional
public class ProductService {
private ProductRepository productRepository;
private Pageable pageable;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Page<Product> list(int page) {
Sort sort = Sort.by("createdAt").descending();
pageable = PageRequest.of(page - 1, 8, sort);
return productRepository.findAll(pageable);
}
public int pages() {
return productRepository.findAll(pageable).getTotalPages();
}
}
ProductsController
@RestController
public class ProductsController {
private ProductService productService;
public ProductsController(ProductService productService) {
this.productService = productService;
}
@GetMapping("products")
@ResponseStatus(HttpStatus.OK)
public ProductsDto list(
@RequestParam(required = false, defaultValue = "1") Integer page
) {
List<ProductDto> productDtos =
productService.list(page)
.stream()
.map(product -> product.toDto())
.collect(Collectors.toList());
int pageNumber = productService.pages();
return new ProductsDto(productDtos, pageNumber);
}
}
리퀘스트 파람으로 page번호를 매개변수로 받아준후
스트림으로 Dto 리스트로 변환
그리고 변환해준 리스트와 , 아까 총 페이지수를 계산해준 pageNumber까지 받아서 return 해준다.
DTO
public class ProductsDto {
private List<ProductDto> products;
private int pageNumber;
public ProductsDto() {
}
public ProductsDto(List<ProductDto> products, int pageNumber) {
this.products = products;
this.pageNumber = pageNumber;
}
public List<ProductDto> getProducts() {
return products;
}
public int getPageNumber() {
return pageNumber;
}
}
그리고 리턴해주는 ProductsDto 타입에 int PageNumber 를 같이 받아주고 게터와 생성자를 만들어준다.
그럼 백엔드는 일단 완성
React
ApiService
에서
async fetchProducts() {
const url = `${baseUrl}/products`;
const { data } = await axios.get(url);
const { products, pageNumber } = data;
return { products, pageNumber };}
products 라는 리스트와 페이지 넘버를 같이 받아와줌.
ProductsStore에서
pageNumbers와 products 를 모두 배열로 지정해주고(pageNumbers 철자 주의!)
export default class ProductsStore {
constructor() {
this.listeners = new Set();
this.pageNumbers = [];
this.products = [];
}
async fetchProducts() {
this.products = [];this.publish();
const { products, pageNumber } = await apiService.fetchProducts();
this.products = products;
this.pageNumbers = [...Array(pageNumber)].map((number, index) => index + 1);
this.publish();}
api 백엔드 서버에서 받아오는 pageNumber를 맵핑을 통해서 인덱에 1씩 더한 값으로 배열을 만들어줌.
Productspage
export default function ProductsPage() {
const productsStore = useProductsStore();
useEffect(() => {
productsStore.fetchProducts();
}, []);
const navigate = useNavigate();
const { products, pageNumbers } = productsStore;
const handleClickPageButton = (number) => {
productsStore.changePageNumber(number);
navigate(`/products?page=${number}`);
};
return (
<Products
products={products}
pageNumbers={pageNumbers}
onClickPageButton={handleClickPageButton}
/>
);
}
페이지 버튼을 클릭하면 이동할 함수를 아래와 같이 만들어주자!
apiservice에서
async changePageNumber(number) {
const url = `${baseUrl}/products`;
const { data } = await axios.get(url, {params: {page: number,},});return data.products;}
store에서
async changePageNumber(number) {
this.products = [];
this.products = await apiService.changePageNumber(number);this.publish();}
products 컴포넌트에서
<nav>
<ul>{pageNumbers.map((number) => (<li key={number}><buttontype="button"onClick={() => handleClickPageButton(number)}>{number}</button></li>))}</ul></nav>
일단 요기까지...
복습하고 다시 정리하자!
'개발 관련 학습 및 문제해결' 카테고리의 다른 글
react router dom 로그인 문제 해결[20221012 TIL] (0) | 2022.10.12 |
---|---|
뭐든 테스트 코드 부터...[20221011 TIL] (0) | 2022.10.11 |
리액트에서 이미지 가져오기[20221005 TIL] (0) | 2022.10.05 |
메가테라 레벨테스트2 1주차 중간 회고[20221004 TIL] (0) | 2022.10.04 |
스프링부트 Whitelabel Error Page 에러 해결방법[20221003 TIL] this application has no explicit mapping for (1) | 2022.10.03 |
댓글