Здраствуйте, есть компонент
components/pages/ShopPage.jsx
import React, { Component } from 'react';
import ProductSingle from '../products/ProductSingle';
import CatsListFilterShop from '../../containers/CatsListFilterShop';
import ProductsSortShop from '../../containers/ProductsSortShop';
import {Pagination} from "../../helpers/pagination";
import Breadcrumbs from "../../helpers/breadcrumbs";
class ShopPage extends Component {
componentDidMount() {
const { setProducts, setAllProducts } = this.props;
setAllProducts();
}
render(){
const {productsList, categories, isProductsReady, setPagination, currentPage, pager} = this.props;
const matchPath = this.props.match.path;
return (
<div className="container woocomm__container">
<div className="row woocomm__row">
<div className="col-xs-12">
<div className="woocomm__col">
<Breadcrumbs />
<div className="products__wrapper">
<div className="products__sidebar">
{isProductsReady && <CatsListFilterShop categories={categories} />}
</div>
<div className="products__content">
<div className="products__contentHeader">
<div className="products__contentHeaderTitle">Весь ассортимент</div>
<ProductsSortShop />
</div>
<div className="products__list">
{isProductsReady && (
productsList ? (
productsList.map( ( productData ) => {
return (
<div className={'good__item'} key={productData.id}>
<ProductSingle {...productData} matchPath={matchPath} />
</div>
);
})) : (
<div className="products__list-empty">В этой категории товаров нет</div>
)
)}
</div>
{pager && (
<Pagination
pager={pager}
page={currentPage}
setPagination={setPagination.bind(this)}
/>
)}
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default ShopPage;
и его контейнер в котором происходит фильтрация и прочая обработка данных.
containers/pages/ShopPage.js
import {connect} from 'react-redux';
import {setProducts, setAllProducts} from '../../actions/products';
import {setFilter, setPagination} from '../../actions/filter';
import ShopPage from '../../components/pages/ShopPage';
import {getPager} from "../../helpers/pagination";
import {getCategoryProductRelationsByCatSlug} from '../../helpers/getCategoryProductRelations';
function sortBy(products, sortBy){
switch(sortBy){
case 'price_asc':
return products && products.sort((a, b) => (a.regular_price - b.regular_price));
case 'price_desc':
return products && products.sort((a, b) => (b.regular_price - a.regular_price))
default:
return products && products;
}
}
function getVisibleProducts(products, filterBy, catsRelation){
switch(filterBy){
case "all":
return products && products;
default:
const productIDs = catsRelation[filterBy] ? catsRelation[filterBy] : [];
return products && products.filter(item => (productIDs.includes(item.id)));
}
}
function getPaginatedProducts(products, page, perPage){
const end = page * perPage;
const begin = end - perPage;
return products && products.slice(begin, end);
};
function getPages(visibleProducts, perPage){
return Math.ceil(visibleProducts && visibleProducts.length / perPage);
};
const mapStateToProps = ({products, filter}) => {
const categoriesRelationship = getCategoryProductRelationsByCatSlug( products.items.categoriesRelationship );
const visibleProducts = getVisibleProducts(
products.items.productsList,
filter.filterShopBy,
categoriesRelationship
);
const sortedProducts = sortBy(
visibleProducts,
filter.sortProductShopBy
);
/* START: Pagination */
const perPage = 9;
const currentPage = filter.page || 1;
const paginatedProducts = getPaginatedProducts(
sortedProducts,
currentPage,
perPage
);
const pager = getPager(
visibleProducts && visibleProducts.length,
currentPage,
perPage
);
/* END: Pagination */
return {
productsList: paginatedProducts,
categories: products.items.categories,
categoriesRelationship: categoriesRelationship,
isProductsReady: products.isProductsReady,
filterBy: filter.filterShopBy,
sortProductShopBy: filter.sortProductShopBy,
pager: pager,
currentPage: currentPage,
}
};
const mapDispatchToProps = dispatch => ({
setAllProducts: () => dispatch(setAllProducts()),
setProducts: products => dispatch(setProducts(products)),
setPagination: page => dispatch(setPagination(page)),
setFilter,
});
export default connect(mapStateToProps, mapDispatchToProps)(ShopPage);
соответственно
actions/products.js
import {
SET_PRODUCTS,
SET_PRODUCTS_SUCCEEDED,
SET_PRODUCTS_FAILED,
} from './types/product-types';
export const setAllProducts = () => {
return async dispatch => {
dispatch({type: SET_PRODUCTS});
axios.get('/api/products').then(({data}) =>{
dispatch({type: SET_PRODUCTS_SUCCEEDED, payload: data});
}).catch(err => {
dispatch({type: SET_PRODUCTS_FAILED, payload: err});
});
};
};
и
reducers/products.js
import {
SET_PRODUCTS,
SET_PRODUCTS_SUCCEEDED,
SET_PRODUCTS_FAILED,
} from '../actions/types/product-types';
const INITIAL_STATE = {
isProductsReady: false,
isProductsLoading: false,
productsError: null,
items: [],
};
export default function (state = INITIAL_STATE,action){
switch (action.type) {
case SET_PRODUCTS:
return {
...state,
isProductsReady: false,
isProductsLoading: true,
};
case SET_PRODUCTS_SUCCEEDED:
return {
...state,
items: action.payload,
isProductsReady: true,
isProductsLoading: false,
};
case SET_PRODUCTS_FAILED:
return {
...state,
isProductsReady: false,
isProductsLoading: false,
productsError: action.payload
};
default:
return state;
}
}
Правильно ли проводить фильтрацию в контейнере или это нужно делать в reducer или в actions?
Спасибо.