【问题标题】:How to filter an array object in a reducer without affecting the actual state如何在reducer中过滤数组对象而不影响实际状态
【发布时间】:2020-06-14 14:19:19
【问题描述】:

我正在尝试从数组中过滤一个对象(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
    }
}

这个 reducer 总是更新实际状态。为什么这不创建一个新的过滤数组?

【问题讨论】:

  • 这段代码没有问题。请显示动作创建者,你在哪里调用它,以及你在组件中使用状态的位置,这会让你相信它不会更新。
  • @cbr 如何使用扩展运算符进行复制?
  • 您能澄清一下您的问题吗? .filter 创建一个新数组,它不会改变旧数组。 “总是更新实际状态”和“不制作新的过滤数组”是什么意思?
  • @cbr 一旦 SEARCH_PRODUCT 案例工作,在调用 LIST_ALL_PRODUCTS 案例时,它会返回一个空数组。

标签: javascript arrays reactjs redux


【解决方案1】:

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

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.toLowerCase();
    }
    default:
      return state;
  }
};

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

在 productNameFilter reducer 中,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)
  );

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

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

【讨论】:

    【解决方案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 中使用单一数据源,并在组件本身中做过滤逻辑。 See sample demo here 如果有帮助的话。

    【讨论】:

    • 当然,我什至建议只存储过滤器本身并在组件中进行。
    • @cbt 那也太好了,能否请您告诉我如何在组件中执行此操作的想法?
    • 请参阅答案中提到的演示链接......它有完整的示例代码:)
    猜你喜欢
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2017-03-26
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多