如何过滤这些数据?
How can I filter this data?
我有一个 productSlice 如下:
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) => {
},
},
});
在 ProductSection.js
中,我的类别设置如下:
<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>
我想要实现的是当按下一个类别时,产品将被过滤以仅显示与该类别匹配的产品。但是当category值为'All'
时,所有的产品都会显示出来。 filteredList
数组用于根据所选类别过滤的产品,searchResult
用于根据用户输入值过滤的产品。 hasAppliedFilter
应该检查用户是否在过滤,否则显示所有产品。
我假设您想在电子商务应用程序中实现搜索输入和类别选项卡。
第 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,
第 2 步:在搜索组件中提取状态并过滤它们
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>
)
}
注意:以下是 filterProducts 的一些有趣的测试用例
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)
})
我有一个 productSlice 如下:
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) => {
},
},
});
在 ProductSection.js
中,我的类别设置如下:
<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>
我想要实现的是当按下一个类别时,产品将被过滤以仅显示与该类别匹配的产品。但是当category值为'All'
时,所有的产品都会显示出来。 filteredList
数组用于根据所选类别过滤的产品,searchResult
用于根据用户输入值过滤的产品。 hasAppliedFilter
应该检查用户是否在过滤,否则显示所有产品。
我假设您想在电子商务应用程序中实现搜索输入和类别选项卡。
第 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,
第 2 步:在搜索组件中提取状态并过滤它们
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>
)
}
注意:以下是 filterProducts 的一些有趣的测试用例
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)
})