React/ Redux select 使用 selectors 过滤和排序
React/ Redux select filtering and sorting using selectors
我有一个项目列表,我希望用户能够按属性对这些项目进行排序和过滤。我认为使用 selectors 是执行此操作的最有效方法,但我不确定具体怎么做?理想情况下,我希望用户从列表上方的下拉列表中 select 一个属性,然后将属性的实际值输入到文本字段中,这将触发过滤 select 或使用这两个参数.例如,在汽车列表中,用户想要按“制造商”进行过滤,因此他们从“制造商”、“型号”、“年份”等其他属性列表中选择“制造商”,然后在旁边他们可以输入“Nissan”,然后他们会得到一份仅由 Nissan 制造的汽车的列表。
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchItems } from "../../actions/items";
const ItemList = ({ match }) => {
const items = useSelector((state) => state.items);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchItems());
}, [dispatch]);
const renderedList =
Object.values(items).length > 0
? Object.values(items)
.map((item) => {
return (
<ListItem key={item.id}>
<ItemCard item={item} handleClick={handleClick} />
</ListItem>
);
})
: null;
return (
<Grid container direction="row" className={classes.cardGrid}>
<Grid item lg={4} className={classes.list}>
<Typography variant="h4" className={classes.title}>
Items
</Typography>
<List dense>{renderedList}</List>
</Grid>
</Grid>
);
};
export default ItemList;
将过滤属性和值保持在 Redux 状态,然后在选择器中应用过滤。
// selectors.js
const getFilterAttribute = state => state.filterAttribute;
const getFilterValue = state => state.filterValue;
const getFilteredItems = state => {
const filterAttribute = getFilterAttribute(state);
const filterValue = getFilterValue(state);
const items = getItems(state);
if (!filterAttribute || !filterValue) {
return items;
}
// apply your filter the way you need it
return Object.values(items).filter(...)
}
这有助于将状态选择逻辑与表示逻辑分开。现在您的组件只需调用选择器:
// ItemList.js
const ItemList = (props) => {
const items = useSelector(getFilteredItems);
const renderedList = items.map(item => ...)
return (
...
)
}
编辑:
过滤器组件可能如下所示:
const FilterControl = () => {
const dispatch = useDispatch();
const [attribute, setAttribute] = useState('');
const [value, setValue] = useState('');
const onSubmit = () => {
dispatch({ type: 'SET_FILTER', attribute, value });
}
return (
<div>
<label>Attribute</label>
<input value={attribute} onChange={e => setAttribute(e.target.value)} />
<label>Value</label>
<input value={value} onChange={e => setValue(e.target.value)} />
<button onClick={onSubmit}>Filter</button>
</div>
)
}
我有一个项目列表,我希望用户能够按属性对这些项目进行排序和过滤。我认为使用 selectors 是执行此操作的最有效方法,但我不确定具体怎么做?理想情况下,我希望用户从列表上方的下拉列表中 select 一个属性,然后将属性的实际值输入到文本字段中,这将触发过滤 select 或使用这两个参数.例如,在汽车列表中,用户想要按“制造商”进行过滤,因此他们从“制造商”、“型号”、“年份”等其他属性列表中选择“制造商”,然后在旁边他们可以输入“Nissan”,然后他们会得到一份仅由 Nissan 制造的汽车的列表。
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchItems } from "../../actions/items";
const ItemList = ({ match }) => {
const items = useSelector((state) => state.items);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchItems());
}, [dispatch]);
const renderedList =
Object.values(items).length > 0
? Object.values(items)
.map((item) => {
return (
<ListItem key={item.id}>
<ItemCard item={item} handleClick={handleClick} />
</ListItem>
);
})
: null;
return (
<Grid container direction="row" className={classes.cardGrid}>
<Grid item lg={4} className={classes.list}>
<Typography variant="h4" className={classes.title}>
Items
</Typography>
<List dense>{renderedList}</List>
</Grid>
</Grid>
);
};
export default ItemList;
将过滤属性和值保持在 Redux 状态,然后在选择器中应用过滤。
// selectors.js
const getFilterAttribute = state => state.filterAttribute;
const getFilterValue = state => state.filterValue;
const getFilteredItems = state => {
const filterAttribute = getFilterAttribute(state);
const filterValue = getFilterValue(state);
const items = getItems(state);
if (!filterAttribute || !filterValue) {
return items;
}
// apply your filter the way you need it
return Object.values(items).filter(...)
}
这有助于将状态选择逻辑与表示逻辑分开。现在您的组件只需调用选择器:
// ItemList.js
const ItemList = (props) => {
const items = useSelector(getFilteredItems);
const renderedList = items.map(item => ...)
return (
...
)
}
编辑:
过滤器组件可能如下所示:
const FilterControl = () => {
const dispatch = useDispatch();
const [attribute, setAttribute] = useState('');
const [value, setValue] = useState('');
const onSubmit = () => {
dispatch({ type: 'SET_FILTER', attribute, value });
}
return (
<div>
<label>Attribute</label>
<input value={attribute} onChange={e => setAttribute(e.target.value)} />
<label>Value</label>
<input value={value} onChange={e => setValue(e.target.value)} />
<button onClick={onSubmit}>Filter</button>
</div>
)
}