提问者:小点点

如何在不影响实际状态的情况下在reducer中过滤数组对象


我试图从数组中筛选一个对象(redux reducer),

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
    }
}

这个减速器总是更新实际状态。 为什么这不是一个新的过滤数组?


共2个答案

匿名用户

您可以通过将状态数据结构转换为对象并在redux状态下维护单独的属性来解决问题,例如FilteredData

像这样

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
  }
}

另一种选择

在redux中使用单一数据源,并在组件本身中执行过滤逻辑。 如果有用,请参阅此处的示例演示。

匿名用户

正如我在评论中提到的,您也可以单独存储过滤器本身,并且不在reducer中,而是在组件中进行过滤:

减速器示例:

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;
    }
    default:
      return state;
  }
};

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

在productNameFilter还原程序中,search_product操作的有效负载应包含产品名称筛选器。 重置搜索筛选器就像将状态设置为一样简单。

示例组件,使用挂钩:

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>
  );
};

或使用connect:

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

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

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