【问题标题】:React/ Redux select filtering and sorting using selectorsReact/Redux 使用选择器进行选择过滤和排序
【发布时间】:2020-07-27 15:37:44
【问题描述】:

我有一个项目列表,我希望用户能够按属性对这些项目进行排序和过滤。我认为使用选择器是最有效的方法,但我不确定具体如何?理想情况下,我希望用户从列表上方的下拉列表中选择一个属性,然后将属性的实际值输入到一个文本字段中,这将触发使用这两个参数的过滤选择器。例如,在汽车列表中,用户希望按“品牌”进行过滤,因此他们从“品牌”、“型号”、“年份”等其他属性列表中选择“品牌”,然后他们可以在旁边选择“品牌”输入“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; 

【问题讨论】:

    标签: javascript reactjs redux react-redux reselect


    【解决方案1】:

    将过滤器属性和值保持在 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>
      )
    }
    

    【讨论】:

    • 哇,这太棒了,但我很困惑我如何将属性和值放在首位。我会在我的列表组件中做类似const [filterAttribute, setFilterAttribute] = useState("") 的事情吗?然后在选择属性或输入值时让 set hook 运行 onChange in?
    • 是的,这听起来很对。将这些东西放入自己的组件中可能会有所帮助。我在帖子中添加了更多示例代码以供参考
    • 哈哈,天哪,我现在更困惑了。为什么我要调度动作?我以为我正在使用这种模式来避免这些。对不起,如果我很密集。
    • 好吧,我可能还没有完全清楚。您将过滤器设置存储在 Redux 状态中。要更改这些值,您必须调度一个操作。相反,如果您要将过滤器设置存储在本地组件状态中,那么方法看起来会有些不同。
    • 那么将过滤器设置存储在redux状态是更好的做法吗?我猜是的
    猜你喜欢
    • 1970-01-01
    • 2019-11-04
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多