当选择一个产品时,如何更新产品的过滤器值



我正在做一个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;

当选择一个视图并更新视图时,如何更新过滤器中显示的数据,以便过滤后的数据不再显示在过滤器中?

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

<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(..)

要在选中过滤器时更新它们的值,可以使用"useEffect"钩子来监听"过滤器"中的变化。状态和更新过滤器的值=>

// 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事件(例如,", "。然后,您可以使用此事件来调用您已经定义的handleFilter函数。

Like this =>

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

最新更新