reactjs 如何在选择产品时更新产品筛选器的值

ejk8hzay  于 2022-12-18  发布在  React
关注(0)|答案(2)|浏览(135)

我正在做一个React应用程序,它从后端带来与产品相关的数据,在一个电子商务或商店类型的视图中显示产品,我开发了一个逻辑来过滤根据过滤器参数显示的产品,所以只有匹配过滤器的产品才会被呈现,问题是我不知道如何在选择过滤器时更新它们的值,关于视图被更新但是过滤器的值继续显示被过滤的旧数据。
我现在的密码是

import React ,{useState} from 'react';
import { Card, Breadcrumb, BreadcrumbItem, CardBody} from 'reactstrap';
import {Link} from 'react-router-dom';
// import { Loading } from './LoadingComponent';
import {baseUrl} from '../../shared/baseUrl';

function formatMoney(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}

function RenderStoreItem ({product}) {
  
  //this is a const to retrieve the images that are stored on images/products
  const imagePath = baseUrl + "images/products/";
      return (
          <Card className='product-card'>
              <Link to={ `/store/${product._id}` } style={{textDecoration:"none",color:"black"}}>
                  <img
                    className='card-img-top-store' 
                    src={imagePath + product.marca + "_" + product.linea + "_" + product.modelo + "/" + product.images[0]  } 
                    alt={product.marca} />
                  {/* display the CardTitle inside CardImgOverlay in the right bottom corner */}
                  
                  <CardBody>
                    <h3 >${formatMoney(product.price)}</h3>
                    <div>
                    <h5>{product.marca} - {product.linea}</h5>
                    </div>
                    <h5>{product.modelo}</h5>
                    

                  </CardBody>
              </Link>
          </Card>
      );
  }

const Store= ({products}) =>{

  //this are the filters to apply to the products, so just the products that match the filters will be displayed
  // but if the filter is empty then all the products will be displayed
  const [filter, setFilter] = useState({
    marca: '',
    linea: '',
    modelo: 0
  });

  // this function is called when the user select a filter
  // the filter is stored in the state filter
  // when a filter is selected the products are filtered automatically, no need to click a button

  
  const handleFilter = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;
    setFilter({
      ...filter,
      [name]: value
    });
  }
  
  // this function is called when the user click the button to clear the filters
  // the filter is set to empty
  const clearFilter = () => {
    setFilter({
      marca: '',
      linea: '',
      modelo: 0
    });
  }

  // get distinc values
  const distinctValues = (array, key) => {
    const values = array.map((product) => product[key]);
    const distinctValues = [...new Set(values)];
    return distinctValues;
  }

  // when a filter is selected the products are filtered automatically, no need to click a button
  // the products are filtered by any of the filter selected
  // taking into account that if the filter is empty then all the products will be displayed and that marca is a String, linea is a String and modelo is a number
  const filteredProducts = products.products.filter((product) => {
    if (filter.marca === '' && filter.linea === '' && filter.modelo === 0) {
      return product;
    } else if (filter.marca !== '' && filter.linea === '' && filter.modelo === 0) {
      return product.marca === filter.marca;
    } else if (filter.marca === '' && filter.linea !== '' && filter.modelo === 0) {
      return product.linea === filter.linea;
    } else if (filter.marca === '' && filter.linea === '' && filter.modelo !== 0) {
      return product.modelo == filter.modelo;
    } else if (filter.marca !== '' && filter.linea !== '' && filter.modelo === 0) {
      return product.marca === filter.marca && product.linea === filter.linea;
    } else if (filter.marca !== '' && filter.linea === '' && filter.modelo !== 0) {
      return product.marca === filter.marca && product.modelo == filter.modelo;
    } else if (filter.marca === '' && filter.linea !== '' && filter.modelo !== 0) {
      return product.linea === filter.linea && product.modelo == filter.modelo;
    } else if (filter.marca !== '' && filter.linea !== '' && filter.modelo !== 0) {
      return product.marca === filter.marca && product.linea === filter.linea && product.modelo == filter.modelo;
    }
  });


  const store= filteredProducts.map((product) => {
        return (
          <div key={product.id} id = 'products' className="col-12 col-md-4 py-2">
            <RenderStoreItem product={product}/>
          </div>
        );
    });
      return (
        <div className="container product">
            <div className="row">
                <Breadcrumb>
                    <BreadcrumbItem><Link to="/home">Inicio</Link></BreadcrumbItem>
                    <BreadcrumbItem active>Product</BreadcrumbItem>
                </Breadcrumb>
                <div className="col-12">
                    <h3>Store</h3>
                    <hr />
                </div>                
            </div>
            <div className="row">
              <div className='col-2'>
              {/* here will be the filters selected, will show the data from the products available in the options*/}
                <div className='row'>
                  <div className='col-12'>
                    
                    // HERE are the filters that must be updated
                    <h5>Filtros</h5>

                    <div className='row'>
                      <div className='col-12'>
                        <label htmlFor='marca'>Marca</label>
                        <select className='form-control' name='marca' id='marca' onChange={handleFilter}>
                          <option value=''>Todas</option>
                          {/* display distinct values */}
                          {distinctValues(products.products, 'marca').map((marca) => {
                            return (
                              <option key={marca} value={marca}>{marca}</option>
                            );
                          })}
                          
                        </select>
                      </div>

                      <div className='col-12'>
                        <label htmlFor='linea'>Linea</label>
                        <select className='form-control' name='linea' id='linea' onChange={handleFilter}>
                          <option value=''>Todas</option>
                          {/* display distinct values and next to it the frequency(number of occurences represented by countDistinctValues)*/}
                          {distinctValues(products.products, 'linea').map((linea) => {
                            return (
                              <option key={linea} value={linea}>{linea}</option>
                            );
                          })}
                        </select>
                      </div>

                      <div className='col-12'>
                        <label htmlFor='modelo'>Modelo</label>
                        <select className='form-control' name='modelo' id='modelo' onChange={handleFilter}>
                          <option value=''>Todos</option>
                          {/* display distinct values and next to it the frequency(number of occurences represented by countDistinctValues)*/}
                          {distinctValues(products.products, 'modelo').map((modelo) => {
                            return (
                              <option key={modelo} value={modelo}>{modelo}</option>
                            );
                          })}
                        </select>
                      </div>
                    </div>
                  </div>
                </div>
                
              </div>

              <div className='col-10'>
                <div className='row'>
                {store}
                </div>
              </div>
            </div>
        </div>
      );
  }

export default Store;

当选择了一个筛选器并更新了视图时,如何更新筛选器中显示的数据,以使筛选的数据不再显示在筛选器中?

6rqinv9w

6rqinv9w1#

您可以只使用将要显示的产品来构建选择元素,以便只显示可用选项,而不是使用所有产品来构建选择元素,下面是一个示例:

<select className='form-control' name='linea' id='linea' onChange={handleFilter}>
  <option value=''>Todas</option>
  {distinctValues(filteredProducts, 'linea').map((linea) => {
    return (
      <option key={linea} value={linea}>{linea}</option>
    );
   })}
</select>

在这里,我使用了distinctValues(filteredProducts, 'linea').map(..)而不是distinctValues(products.products, 'linea').map(..)

a9wyjsp7

a9wyjsp72#

要在选择过滤器时更新过滤器的值,可以使用“useEffect”钩子监听“filter”状态的变化并更新过滤器的值=〉

// other code

const Store = ({ products }) => {
  const [filter, setFilter] = useState({
    marca: '',
    linea: '',
    modelo: 0
  });

  // listen for changes in the filter state
  useEffect(() => {
    // update the values of the filters here
  }, [filter]);

  // other code
}

在“useEffect”钩子中,您可以使用“getElementById”获取过滤器的元素,并通过.value属性更新它们的值。

// listen for changes in the filter state

useEffect(() =>{
// update the values of the filters here...
document.getElementByid("marca").value = filter.marca;
// the same for "linea" and "modelo"
, [filter]}

让我知道,如果它清楚或我不明白你的问题
编辑:

第二备选办法

另一种方法是在过滤器元素中添加一个onChange事件(例如,“,“)。2然后你可以使用这个事件来调用你定义的handleFilter函数。
像这样=〉

<select name="marca" value={filter.marca} onChange={handleFilter}>
  <option value="">All</option>
  {distinctValues(products.products, 'marca').map((marca) => (
    <option key={marca} value={marca}>
      {marca}
    </option>
  ))}
</select>

相关问题