Reputation: 173
I have a productSlice as follows:
export const productSlice = createSlice({
name: 'productSlice',
initialState: {
products: [
{
id: 0,
name: 'AutoPart 1',
desc:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
price: 800,
picture: IMAGES.aTeamPerfomance12CircuitWires,
currentQuantity: 1,
category: 'Wiring',
},
...
],
hasAppliedFilter: false,
filteredList: [],
searchResult: [],
selectedCategory: 0,
categories: [
'All',
'Engine & Emissions',
'Lamps & Lighting',
'Brakes & Suspension',
'Tyres & Rims',
'Wiring',
'Electrical',
],
},
reducers: {
filterList: (state, action) => {
},
searchList: (state, action) => {
},
},
});
In ProductSection.js
, I have categories setup as below:
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={{margin: 10, maxHeight: 40}}>
{categories.map((item, index) => {
return (
<TouchableOpacity
style={{
marginBottom: 5,
padding: 2,
}}
onPress={() => dispatch(filterList(index))}>
<Text
style={{
fontWeight: 'bold',
marginRight: 30,
opacity: index == selectedCategory ? 1 : 0.2,
color: theme.text,
...FONTS.body3,
}}>
{item}
</Text>
</TouchableOpacity>
);
})}
</ScrollView>
What I want to achieve is when a category is pressed, the products will be filtered to show only those that match the category. But when the category value is 'All'
, all the products will be displayed. The filteredList
array is meant for products filtered based on the category selected and searchResult
is for products that have been filtered based on input values from the user. hasAppliedFilter
is supposed to check if the user is filtering, else, display all the products.
Upvotes: 0
Views: 56
Reputation: 241
I assume you want to implement a search input and a category tab like in an ecommerce application.
Step 1:
Your Redux state must look like it as per because final products are computable from them (See Thinking in React Step 3 (https://reactjs.org/docs/thinking-in-react.html))
- filteredList: [],
+ selectedCategory:string,
- searchResult: [],
+ searchText:string,
Step 2: In search component extract the state and filter them
import { FC } from 'react'
import { useSelector } from 'react-redux'
export const isEmpty = (param: any) => !param ? true : false
export const isTextContainSearchText = (text: string, searchText: string) => text.indexOf(searchText) > -1
export const isEmptyString = (p: string) => {
if (isEmpty(p) || p!.trim().length === 0) {
return true
} else return false
}
export const filterProducts = (selectedCategory: any, searchText: any, products: any[]) => {
var r = products;
if (selectedCategory !== 'All') {
r = products.filter(({ category }) => category === selectedCategory)
}
if (!isEmptyString(searchText)) {
searchText = searchText.toLowerCase()
r = r.filter(({ name }) => isTextContainSearchText(name.toLowerCase(), searchText))
}
return r
}
const SearchComponent: FC = () => {
const { selectedCategory, searchText, products } = useSelector(state => state.product)
const ps = filterProducts(selectedCategory, searchText, products)
return (
<div>
{JSON.stringify(ps)}
</div>
)
}
import { filterProducts } from "."
test('should filterProducts', () => {
const products = [
{
id: 0,
name: 'AutoPart 1',
desc:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
price: 800,
currentQuantity: 1,
category: 'Wiring',
},
]
expect(filterProducts('All', '', products)).toHaveLength(1)
expect(filterProducts('Wiring', '', products)).toHaveLength(1)
expect(filterProducts('Electicals', '', products)).toHaveLength(0)
expect(filterProducts('All', 'ram', products)).toHaveLength(0)
})
Upvotes: 1