简体   繁体   English

如何在reducer中过滤数组object而不影响实际的state

[英]How to filter an array object in a reducer without affecting the actual state

I'm trying to filter an object from an array (redux reducer),我正在尝试从数组(redux reducer)中过滤 object,

const data = [
    {id: 0, name: 'Printed Men black Shirt', itemCode: 1000, price: 530, currency: '$', manufacturer: 'ColorWorld'},
    {id: 1, name: 'Denim blue white shorts', itemCode: 1001, price: 230, currency: '$', manufacturer: 'ColorWorld'},
    {id: 2, name: 'Solid Men blue pants', itemCode: 1003, price: 1530, currency: '$', manufacturer: 'Mecrono Hipli'},
    {id: 3, name: 'Checkerd Men Blue Shorts', itemCode: 1300, price: 2530, currency: '$', manufacturer: 'Mecrono Hipli Mini'},
    {id: 4, name: 'Self Designed Pant', itemCode: 1056, price: 130, currency: '$', manufacturer: 
];

export const listProducts = (state = data, action) => {
    switch(action.type){
        case LIST_ALL_PRODUCTS: {
            return state;
        }

        case SEARCH_PRODUCT: {
           return state.filter((e)=> e.name.includes(action.payload))
        }

        default: 
        return state
    }
}

This reducer always updates the actual state.这个减速器总是更新实际的 state。 Why this is not making a new filtered array?为什么这不制作一个新的过滤数组?

You can solve your issue by converting the state data structure to an object and maintain a separate property in redux state say filteredData .您可以通过将 state 数据结构转换为 object 来解决您的问题,并在 redux filteredData中维护一个单独的属性。

Like this像这样

const initialState = {
  data: [
    {
      id: 0,
      name: 'Printed Men black Shirt',
      itemCode: 1000,
      price: 530,
      currency: '$',
      manufacturer: 'ColorWorld',
    },
    {
      id: 4,
      name: 'Self Designed Pant',
      itemCode: 1056,
      price: 130,
      currency: '$',
      manufacturer: '',
    },
  ],
  filteredData: [],
}

export const listProducts = (state = initialState, action) => {
  switch (action.type) {
    case LIST_ALL_PRODUCTS: {
      return state
    }

    case SEARCH_PRODUCT: {
      return { ...state, filteredData: state.data.filter((e) => e.name.includes(action.payload)) }
    }

    default:
      return state
  }
}

Another option另外的选择

Use single source of data in redux and do the filtering logic in the component itself.在 redux 中使用单一数据源,并在组件本身中执行过滤逻辑。 See sample demo here if it helps.如果有帮助,请参阅此处的示例演示

As I mentioned in the comment, you can also separately store the filter itself and do the filtering not in the reducer, but in the component:正如我在评论中提到的,您还可以单独存储过滤器本身,而不是在减速器中进行过滤,而是在组件中进行过滤:

Example reducers:减速器示例:

export const listProducts = (state = data, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

export const productNameFilter = (state = "", action) => {
  switch (action.type) {
    case SEARCH_PRODUCT: {
      return action.payload.toLowerCase();
    }
    default:
      return state;
  }
};

// assuming root reducer is:
// combineReducers({ listProducts, productNameFilter })

In the productNameFilter reducer, the SEARCH_PRODUCT action's payload should contain the product name filter.在 productNameFilter reducer 中, SEARCH_PRODUCT操作的有效负载应包含产品名称过滤器。 Resetting the search filter is as simple as setting the state to '' .重置搜索过滤器就像将 state 设置为''一样简单。

Example component, using hooks:示例组件,使用钩子:

const ProductList = () => {
  const products = useSelector((state) => state.listProducts);
  const productFilter = useSelector((state) => state.productNameFilter);

  const shownProducts = products.filter((product) =>
    product.name.toLowerCase().includes(productFilter.toLowerCase())
  );

  return (
    <ul>
      {shownProducts.map((p) => (
        <p key={p.id}>{p.name}</p>
      ))}
    </ul>
  );
};

or with connect :或使用connect

const ProductList = ({ products, productFilter }) => {
  const shownProducts = products.filter((product) =>
    product.name.toLowerCase().includes(productFilter)
  );

  return (
    <ul>
      {shownProducts.map((p) => (
        <p key={p.id}>{p.name}</p>
      ))}
    </ul>
  );
};

export default connect(ProductList)((state) => ({
  products: state.listProducts,
  productFilter: state.productNameFilter,
}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM