Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React/ Redux select filtering and sorting using selectors

I have a list of items that I would like the user to be able to sort and filter by attribute. I figure using selectors is the most efficient way to do this, though I am not sure exactly how? Ideally, I would like the user to select an attribute from a dropdown above the list, then enter the actual value of the attribute into a text field which would trigger a filtering selector using both of those params. For example in a list of cars, the user wants to filter by "make" so they choose "make" from a list of other attributes like "make", "model", "year" etc. and then next to that they could type in "Nissan" and then they get a list of just cars made by 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; 
like image 958
Morks Avatar asked Oct 26 '25 06:10

Morks


1 Answers

Keep the filter attribute and value in Redux state, and then apply the filtering in a selector.

// 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(...)
}

This helps separate the state-selection logic from the presentation logic. Now your component just has to call the selector:

// ItemList.js

const ItemList = (props) => {
  const items = useSelector(getFilteredItems);
  const renderedList = items.map(item => ...)
  
  return (
    ...
  )
}

EDIT:

The filter component might look like:

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>
  )
}
like image 138
brietsparks Avatar answered Oct 28 '25 18:10

brietsparks



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!