diff --git a/packages/peregrine/src/hooks/usePagination.js b/packages/peregrine/src/hooks/usePagination.js
new file mode 100644
index 0000000000..20932c1cda
--- /dev/null
+++ b/packages/peregrine/src/hooks/usePagination.js
@@ -0,0 +1,14 @@
+import { useMemo, useState } from 'react';
+
+export const usePagination = () => {
+ const [currentPage, setCurrentPage] = useState(0);
+ const [totalPages, setTotalPages] = useState(null);
+
+ const paginationState = { currentPage, totalPages };
+ const api = useMemo(() => ({ setCurrentPage, setTotalPages }), [
+ setCurrentPage,
+ setTotalPages
+ ]);
+
+ return [paginationState, api];
+};
diff --git a/packages/peregrine/src/index.js b/packages/peregrine/src/index.js
index d5d3d1738c..2011ab0b5a 100644
--- a/packages/peregrine/src/index.js
+++ b/packages/peregrine/src/index.js
@@ -5,6 +5,7 @@ import * as Util from './util';
export { useApolloContext } from './hooks/useApolloContext';
export { useEventListener } from './hooks/useEventListener';
export { useDropdown } from './hooks/useDropdown';
+export { usePagination } from './hooks/usePagination';
export { useQuery } from './hooks/useQuery';
export { useQueryResult } from './hooks/useQueryResult';
export { useSearchParam } from './hooks/useSearchParam';
diff --git a/packages/venia-concept/src/RootComponents/Category/__tests__/__snapshots__/categoryContent.spec.js.snap b/packages/venia-concept/src/RootComponents/Category/__tests__/__snapshots__/categoryContent.spec.js.snap
new file mode 100644
index 0000000000..f751c3e0dc
--- /dev/null
+++ b/packages/venia-concept/src/RootComponents/Category/__tests__/__snapshots__/categoryContent.spec.js.snap
@@ -0,0 +1,40 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders the correct tree 1`] = `
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/packages/venia-concept/src/RootComponents/Category/__tests__/categoryContent.spec.js b/packages/venia-concept/src/RootComponents/Category/__tests__/categoryContent.spec.js
index 174d5bb88c..69ab9cd6c6 100644
--- a/packages/venia-concept/src/RootComponents/Category/__tests__/categoryContent.spec.js
+++ b/packages/venia-concept/src/RootComponents/Category/__tests__/categoryContent.spec.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import ShallowRenderer from 'react-test-renderer/shallow';
import CategoryContent from '../categoryContent';
@@ -21,15 +21,16 @@ const data = {
}
};
-test('renders with props', () => {
- const pageSize = 6;
- const wrapper = shallow(
+test('renders the correct tree', () => {
+ const shallowRenderer = new ShallowRenderer();
+ const tree = shallowRenderer.render(
- ).dive();
- expect(wrapper.hasClass(classes.root)).toBe(true);
+ );
+
+ expect(tree).toMatchSnapshot();
});
diff --git a/packages/venia-concept/src/RootComponents/Category/category.js b/packages/venia-concept/src/RootComponents/Category/category.js
index 94fe48ac2e..173c4fca58 100644
--- a/packages/venia-concept/src/RootComponents/Category/category.js
+++ b/packages/venia-concept/src/RootComponents/Category/category.js
@@ -1,119 +1,84 @@
-import React, { Component } from 'react';
+import React, { useEffect } from 'react';
import { string, number, shape } from 'prop-types';
-import { compose } from 'redux';
-import { connect, Query } from 'src/drivers';
+import { usePagination, useQuery } from '@magento/peregrine';
-import classify from 'src/classify';
-import { setCurrentPage, setPrevPageTotal } from 'src/actions/catalog';
-import { loadingIndicator } from 'src/components/LoadingIndicator';
+import { mergeClasses } from 'src/classify';
+import categoryQuery from 'src/queries/getCategory.graphql';
import CategoryContent from './categoryContent';
+import { loadingIndicator } from 'src/components/LoadingIndicator';
import defaultClasses from './category.css';
-import categoryQuery from 'src/queries/getCategory.graphql';
-class Category extends Component {
- static propTypes = {
- id: number,
- classes: shape({
- gallery: string,
- root: string,
- title: string
- }),
- currentPage: number,
- pageSize: number,
- prevPageTotal: number
- };
+const Category = props => {
+ const { id, pageSize } = props;
- // TODO: Should not be a default here, we just don't have
- // the wiring in place to map route info down the tree (yet)
- static defaultProps = {
- id: 3
+ const [paginationValues, paginationApi] = usePagination();
+ const { currentPage, totalPages } = paginationValues;
+ const { setCurrentPage, setTotalPages } = paginationApi;
+
+ const pageControl = {
+ currentPage,
+ setPage: setCurrentPage,
+ updateTotalPages: setTotalPages,
+ totalPages
};
- componentDidUpdate(prevProps) {
- // If the current page has changed, scroll back up to the top.
- if (this.props.currentPage !== prevProps.currentPage) {
- window.scrollTo(0, 0);
- }
- }
+ const [queryResult, queryApi] = useQuery(categoryQuery);
+ const { data, error, loading } = queryResult;
+ const { runQuery, setLoading } = queryApi;
+ const classes = mergeClasses(defaultClasses, props.classes);
- render() {
- const {
- id,
- classes,
- currentPage,
- pageSize,
- prevPageTotal,
- setCurrentPage,
- setPrevPageTotal
- } = this.props;
+ useEffect(() => {
+ setLoading(true);
+ runQuery({
+ variables: {
+ id: Number(id),
+ onServer: false,
+ pageSize: Number(pageSize),
+ currentPage: Number(currentPage)
+ }
+ });
- const pageControl = {
- currentPage: currentPage,
- setPage: setCurrentPage,
- updateTotalPages: setPrevPageTotal,
- totalPages: prevPageTotal
- };
+ window.scrollTo({
+ left: 0,
+ top: 0,
+ behavior: 'smooth'
+ });
+ }, [id, pageSize, currentPage]);
- return (
-
- {({ loading, error, data }) => {
- if (error) return Data Fetch Error
;
- // If our pagination component has mounted, then we have
- // a total page count in the store, so we continue to render
- // with our last known total
- if (loading)
- return pageControl.totalPages ? (
-
- ) : (
- loadingIndicator
- );
+ const totalPagesFromData = data
+ ? data.category.products.page_info.total_pages
+ : null;
+ useEffect(() => {
+ setTotalPages(totalPagesFromData);
+ }, [totalPagesFromData]);
- // TODO: Retrieve the page total from GraphQL when ready
- const pageCount =
- data.category.products.total_count / pageSize;
- const totalPages = Math.ceil(pageCount);
- const totalWrapper = {
- ...pageControl,
- totalPages: totalPages
- };
+ if (error) return Data Fetch Error
;
+ // show loading indicator until our data has been fetched and pagination state has been updated
+ if (!totalPages) return loadingIndicator;
- return (
-
- );
- }}
-
- );
- }
-}
+ // if our data is still loading, we want to reset our data state to null
+ return (
+
+ );
+};
-const mapStateToProps = ({ catalog }) => {
- return {
- currentPage: catalog.currentPage,
- pageSize: catalog.pageSize,
- prevPageTotal: catalog.prevPageTotal
- };
+Category.propTypes = {
+ id: number,
+ classes: shape({
+ gallery: string,
+ root: string,
+ title: string
+ }),
+ pageSize: number
+};
+
+Category.defaultProps = {
+ id: 3,
+ pageSize: 6
};
-const mapDispatchToProps = { setCurrentPage, setPrevPageTotal };
-export default compose(
- classify(defaultClasses),
- connect(
- mapStateToProps,
- mapDispatchToProps
- )
-)(Category);
+export default Category;
diff --git a/packages/venia-concept/src/RootComponents/Category/categoryContent.js b/packages/venia-concept/src/RootComponents/Category/categoryContent.js
index 8f16bf20e4..148d2544a0 100644
--- a/packages/venia-concept/src/RootComponents/Category/categoryContent.js
+++ b/packages/venia-concept/src/RootComponents/Category/categoryContent.js
@@ -1,36 +1,35 @@
-import React, { Component } from 'react';
-import classify from 'src/classify';
+import React from 'react';
+import { mergeClasses } from 'src/classify';
import Gallery from 'src/components/Gallery';
import Pagination from 'src/components/Pagination';
import defaultClasses from './category.css';
-class CategoryContent extends Component {
- render() {
- const { classes, pageControl, data, pageSize } = this.props;
- const items = data ? data.category.products.items : null;
- const title = data ? data.category.description : null;
- const categoryTitle = data ? data.category.name : null;
+const CategoryContent = props => {
+ const { pageControl, data, pageSize } = props;
+ const classes = mergeClasses(defaultClasses, props.classes);
+ const items = data ? data.category.products.items : null;
+ const title = data ? data.category.description : null;
+ const categoryTitle = data ? data.category.name : null;
- return (
-
-
- {/* TODO: Switch to RichContent component from Peregrine when merged */}
-
- {categoryTitle}
-
-
-
-
- );
- }
-}
+ return (
+
+
+ {/* TODO: Switch to RichContent component from Peregrine when merged */}
+
+ {categoryTitle}
+
+
+
+
+ );
+};
-export default classify(defaultClasses)(CategoryContent);
+export default CategoryContent;
diff --git a/packages/venia-concept/src/components/Pagination/__tests__/pagination.spec.js b/packages/venia-concept/src/components/Pagination/__tests__/pagination.spec.js
index 67710b9d8c..97af945b0b 100644
--- a/packages/venia-concept/src/components/Pagination/__tests__/pagination.spec.js
+++ b/packages/venia-concept/src/components/Pagination/__tests__/pagination.spec.js
@@ -185,13 +185,3 @@ test('rightSkip skips toward last page', () => {
expect(setPage).toHaveBeenCalledTimes(1);
expect(setPage).toHaveBeenLastCalledWith(8);
});
-
-test('updateTotalPages is called on component mount', () => {
- TestRenderer.create(
-
-
-
- );
-
- expect(updateTotalPages).toHaveBeenCalledTimes(1);
-});
diff --git a/packages/venia-concept/src/components/Pagination/pagination.js b/packages/venia-concept/src/components/Pagination/pagination.js
index 3206e63b87..6d256b22c8 100644
--- a/packages/venia-concept/src/components/Pagination/pagination.js
+++ b/packages/venia-concept/src/components/Pagination/pagination.js
@@ -27,11 +27,6 @@ class Pagination extends Component {
};
componentDidMount() {
- // updateTotalPages pushes the current page count of a category query to
- // redux so it knows how many tiles to render even in the Query
- // component's loading state
- const { updateTotalPages, totalPages } = this.props.pageControl;
- updateTotalPages(totalPages);
this.syncPage();
}
diff --git a/packages/venia-concept/src/queries/getCategory.graphql b/packages/venia-concept/src/queries/getCategory.graphql
index 97762d5248..22b56ce9d9 100644
--- a/packages/venia-concept/src/queries/getCategory.graphql
+++ b/packages/venia-concept/src/queries/getCategory.graphql
@@ -21,6 +21,9 @@ query category($id: Int!, $pageSize: Int!, $currentPage: Int!, $onServer: Boolea
}
}
}
+ page_info {
+ total_pages
+ }
total_count
}
meta_title @include(if: $onServer)