I have search filter and sort inputs on the same component.I'm using reselect(selector package) where the data array is filtered and sorted. The mapStateToProps is updating the component on each search filter result.but the mapStateToProps is not updating the component after sorting the array.
selectors/index.js
import { createSelector } from 'reselect'
const getListOfCategory = (state) => state.products.product
const getSearchText = (state) => state.products.searchText
const getSortValue = (state) => state.products.sortValue
export const getVisibleCategory = createSelector(
[ getListOfCategory, getSearchText, getSortValue ],
(ListOfCategory, searchText, sortValue) =>{
if((searchText !== undefined) && (searchText !== null) && (searchText !== "")){
return ListOfCategory.filter((val) => val.modelname.toLowerCase().includes(searchText.toLowerCase())).sort((a, b) => {
if (sortValue === 'likes') {
return b.modellikes - a.modellikes;
}
if (sortValue === 'views') {
return b.modelviews - a.modelviews;
}
if (sortValue === 'brand') {
return a.modelname > b.modelname ? 1 : a.modelname < b.modelname ? -1 : 0;
}
});
}
if(sortValue){
return ListOfCategory.sort((a, b) => {
if (sortValue === 'likes') {
return b.modellikes - a.modellikes;
}
if (sortValue === 'views') {
return b.modelviews - a.modelviews;
}
if (sortValue === 'brand') {
return a.modelname > b.modelname ? 1 : a.modelname < b.modelname ? -1 : 0;
}
});
}
}
)
Here is my react component.
import React from 'react';
import {connect} from 'react-redux';
import {getCategoryInfo,search,sortBy} from '../actions/productActions';
import {getVisibleCategory} from '../selectors';
import {Link} from 'react-router-dom';
class SmartCategory extends React.Component{
constructor(props){
super(props);
this.state={
searchFilter:""
}
this.searchHandle=this.searchHandle.bind(this);
this.sortHandle=this.sortHandle.bind(this);
}
searchHandle(e){
this.setState({
searchFilter:e.target.value
});
this.props.search(e.target.value);
}
sortHandle(e){
this.props.sortBy(e.target.value);
}
componentDidMount(){
this.props.getCategoryInfo(this.props.page,this.props.pageId);
}
componentWillReceiveProps(nextProps){
if(nextProps.page !== this.props.page || nextProps.pageId !== this.props.pageId){
this.props.getCategoryInfo(nextProps.page,nextProps.pageId);
}
}
changeText(){
if(this.props.categoryTitle != undefined){
let categoryTitle=this.props.categoryTitle.charAt(0).toUpperCase() + this.props.categoryTitle.slice(1);
categoryTitle=categoryTitle.split('_').join(' ');
return categoryTitle;
}
}
render(){
const {error,isLoading}=this.props
if(error) return <ResourceNotFound error={error}/>;
if(isLoading) return <div className="spinner"></div>;
return (
<div className="container-fluid mb-4 categoryWrapper">
<div className="row mx-0 pt-4">
<div className=" col-sm-2 col-md-2 col-lg-2 px-2">
<div className="input-group mb-3">
<div className="input-group-prepend">
<span className="input-group-text" id="basic-addon1"><i className="fa fa-search" aria-hidden="true"></i></span>
</div>
<input type="text"
className="form-control"
placeholder="Search by brand"
onChange={this.searchHandle}
value={this.state.searchFilter}
/>
</div>
</div>
<div className=" col-sm-2 col-md-2 col-lg-2 px-2">
<div className="form-group">
<select className="form-control" id="sel1"
placeholder="-- Sort By -- "
onChange={this.sortHandle}
>
<option disabled>-- Sort By --</option>
<option value="brand" >Brand</option>
<option value="likes">Likes</option>
<option value="views">Views</option>
</select>
</div>
</div>
</div>
<div className="row mx-0 py-3">
{this.props.isLoading ? <div className="spinner"></div> : null}
{this.props.product && this.props.product.map((product,i)=>
<div className="col-sm-3 col-md-3 col-lg-3" key={product.id}>
<Link to={`/SmartView/${this.props.page}/${product.modelname}`} className="routeDecorator">
<div className="border mb-2 p-3 rounded ">
<span className="text-grey">
<span className="mr-2">
<i className="fa fa-thumbs-o-up" aria-hidden="true"> {product.modellikes}</i>
</span>
<span className="float-right">
<i className="fa fa-eye" aria-hidden="true"> {product.modelviews} views</i>
</span>
</span>
</div>
</Link>
</div>
)}
</div>
</div>
);
}
}
function mapStateToProps(state){
const {isLoading,isLoaded,error,categoryTitle,product,searchText,sortValue} = state.products
return {
isLoading,
error,
product:getVisibleCategory(state) || product,
categoryTitle
}
}
export default connect(mapStateToProps,{getCategoryInfo,search,sortBy})(SmartCategory);