【问题标题】:React.JS - Can't Seem To Filter Products Array (Always Shows Null)React.JS - 似乎无法过滤产品数组(总是显示为空)
【发布时间】:2022-06-18 12:17:09
【问题描述】:

所以我目前正在学习 React,并且正在关注它的教程。有一点我已经坚持了好几个小时,它试图实现一个“过滤”系统来过滤掉连接的 MongoDB 数据库中具有这些属性的产品。

我们有所有产品的页面:

import React from 'react'
import styled from 'styled-components'
import Announcement from '../Components/Announcement';
import Footer from '../Components/Footer';
import Navbar from '../Components/Navbar';
import Newsletter from '../Components/Newsletter';
import Products from '../Components/Products';
import { useLocation } from 'react-router-dom';
import { useState } from 'react';

const Container = styled.div`

`;

const Title = styled.h1`
    margin: 20px;
`;

const FilterContainer = styled.div`
    display: flex;
    justify-content: space-between;
`;

const Filter = styled.div`
    margin: 20px;
`;

const FilterText = styled.span`
    font-size: 20px;
    font-weight: 600;
    margin-right: 20px;
`

const Select = styled.select`
    padding: 10px;
    margin-right: 20px;
`;

const Option = styled.option``;


export const ProductList = () => {

  const location = useLocation();
  const category = location.pathname.split('/')[2];

  const [filters, setFilters] = useState({});
  const [sort, setSort] = useState("newest");

  const handleFilters = (e) => {
      const value = e.target.value;
      setFilters({
          ...filters,
          [e.target.name]: value
      });
  };

  return (
    <Container>
        <Navbar />
        <Announcement />
        <Title> {category} </Title>
        <FilterContainer>
            <Filter>
                <FilterText> Filter Products: </FilterText>
                <Select name="color" onChange={handleFilters}>
                    <Option disabled>
                        Color
                    </Option>
                    <Option> white </Option>
                    <Option> black </Option>
                    <Option> red </Option>
                    <Option> blue </Option>
                    <Option> yellow </Option>
                    <Option> green </Option>
                </Select>
                <Select name="size" onChange={handleFilters}>
                    <Option disabled>
                        Size
                    </Option>
                    <Option> XS </Option>
                    <Option> S </Option>
                    <Option> M </Option>
                    <Option> L </Option>
                    <Option> XL </Option>
                </Select>
            </Filter>
            <Filter>
                <FilterText> Sort Products: </FilterText>
                <Select onChange={e=>setSort(e.target.value)}>
                    <Option value="newest"> Newest </Option>
                    <Option value="asc"> Price (asc) </Option>
                    <Option value="desc"> Price (desc) </Option>
                </Select>
            </Filter>
        </FilterContainer>
        <Products category={category} filters={filters} sort={sort} />
        <Newsletter />
        <Footer />
    </Container>
  )
}

我们有单独的产品组件:

import React from 'react'
import styled from 'styled-components'
import Product from './Product';
import { popularProducts } from '../products.js'
import { useState } from 'react';
import { useEffect } from 'react';
import axios from 'axios';

const Container = styled.div`
    padding: 20px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
`;

const Products = ({ category, filters, sort }) => {

  const [products, setProducts] = useState([]);
  const [filteredProducts, setFilteredProducts] = useState([]);

  useEffect(() => {
    const getProducts = async () => {
      try {
        const res = await axios.get(
          category
            ? `http://localhost:5000/api/products?category=${category}`
            : "http://localhost:5000/api/products"
        );
        setProducts(res.data);
      } catch (err) {}
    };
    getProducts();
  }, [category]);

  useEffect(() => {
    category &&
      setFilteredProducts(
        products.filter((item) =>
          Object.entries(filters).every(([key, value]) =>
            item[key].includes(value)
          )
        )
      );
  }, [products, category, filters]);

  console.log(filteredProducts);
  return (
    <Container>
        {filteredProducts.map(item => (
            <Product item={item} key={item.id} />
        ))}
    </Container>
  )
}

export default Products;

哪里出错了,filteredProducts 总是空的,我有setFilteredProducts 的行总是抛出一个错误,说Uncaught TypeError: Cannot read properties of undefined (reading 'includes')。现在,我不确定这是否有足够的信息,这是一个相当大的项目,但我已经逐行按照本部分中的教程进行操作,所以我很迷茫为什么它不起作用。

这是产品 MongoDB 部分中的一个条目。我真的迷路了。

_id
:
6210fb1e76a358ed883ab6f8
title: "Cloud Shoes"
description: "Black, classic shoe"
image:"https://images.ctfassets.net/od02wyo8cgm5/7mUcvgGL2UYQNSIOJKAy9N/0bbd9..." categories:Array
size: Array
colors:Array
price:19.99
inStock:true
createdAt:2022-02-19T14:13:50.802+00:00
updatedAt:2022-02-19T14:13:50.802+00:00
__v:0

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您的代码中似乎有一个错字(&lt;Select&gt; 元素的 name 属性)。

    只是改变

    <Select name="color" onChange={handleFilters}>
    

    <Select name="colors" onChange={handleFilters}>
    

    你可以走了。

    但你问为什么?继续阅读...

    根据您的代码,传递给 Products 组件的 filters 属性具有以下结构:

    let filters = {
            color: String,
            size: String
          };
    

    但是,product 数据(来自数据库)具有Array 类型的属性colorssize 类型的Array 属性。我假设您正在使用这些属性来过滤产品。

    如果是这种情况,那么传递给Products 组件的filters 属性应该具有这种结构(注意colors 不是color):

    let filters = {
          colors: String,
          size: String,
        };
    

    然后,给定products 中的Array,每个product 都具有这种结构:

    let product = {
          ...others,
          colors: Array,
          size: Array
        };
    

    这段代码应该可以工作:

    products.filter((item) =>
        Object.entries(filters)
              .every(([key, value]) =>
                   item[key].includes(value)
               )
        );
    

    key 将是 colorssizeitem[key].includes(value) 将按预期返回 truefalse,具体取决于 value

    至于错误;在您的代码中,keycolorsize。结果,item[color] 正在返回 undefined(应该如此),因为 product 没有该属性。然后尝试undefined.includes(value) 失败(应该如此)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      相关资源
      最近更新 更多