首页 > 解决方案 > 如何在 React 中过滤产品

问题描述

再会,

我是 React 的新手,我正在制作我的第一个电子商务网站。我的问题是:如何按尺寸过滤我的产品?我实在想不出其中的逻辑。预先感谢您的回答。我也尝试过使用 Redux,但没有成功,它给了我以下错误:× TypeError: Cannot read property 'items' of undefined

代码产品卡:

import React,{useState,useEffect} from 'react'
import {Link} from 'react-router-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {Library} from '@fortawesome/fontawesome-svg-core'
import {faShoppingBasket} from '@fortawesome/free-solid-svg-icons'
import {useDispatch, useSelector} from 'react-redux'
import { listProduct, Filterproducts } from '../../actions/productActions'



function Product(props){
    //default value is an array, because we've got data in an array 
    const [qty,setQty] = useState(1)
    const productList = useSelector(state=>state.productList)
    const{products,loading,error}=productList
    const dispatch = useDispatch()
    
    // handlefilter

  

    useEffect(()=> {
        dispatch(listProduct())
       


  

    }, [])

    // handle cart adding
    const handleAddToCart = ()=> {
        props.history.push('/cart/' + props.match.params.id +  "?qty" +qty)
    }


  


   
    return( 
        // Check the loading before rendering products
        loading? <div><h1 className="load">loading...</h1></div> : 
        error?<div>{error}</div>:
           <ul className="products">
               
            {products.map(product=> (
        
            <li key={product.id} className="product"> 
             <Link to={"/product/" + product.id}><div className="img" style={{background: `url(${product.img})`, backgroundSize: 'cover'}}></div></Link>
                   {/* LOOK OUT FOR TYPOS IN ROUTIING  dont put':' after /, this only applies
                   when routing because the ": " implies for a parameter
                   In this case you can directly access product.id  */}
               <Link to={"/product/" +  product.id}><h1>{product.name}</h1></Link> 
                <p> <small>€&lt;/small>{product.price}</p>
                <div>size: {product.size}</div>
              
                {product.qty > 0 ? <div><button onClick={handleAddToCart}>Add to cart</button>  <div>{product.qty} left</div></div> : <div>out of stock</div> }   
               
             
                
                </li> 
                )
                
                )}
   
                 </ul>
                 
       
    
    )
}
export default Product

代码产品操作:

import Axios from 'axios'
import {
    PRODUCT_LIST_FAIL, 
    PRODUCT_LIST_REQUEST, 
    PRODUCT_LIST_SUCCESS, 
    PRODUCT_DETAILS_REQUEST,
    PRODUCT_DETAILS_SUCCESS,
    PRODUCT_DETAILS_FAIL,
    FILTER_PRODUCTS_BY_PRICE,
    FILTER_PRODUCTS_BY_SIZE} from '../constants/productConstants'



const listProduct = () => async(dispatch)=> {
    
        try{
            dispatch({type:PRODUCT_LIST_REQUEST})
            fetch('http://localhost:5000/')
            .then(res=> res.json())
            .then(data=> dispatch({type: PRODUCT_LIST_SUCCESS, payload:data}) )
           
        }
        catch(error){
            dispatch({type: PRODUCT_LIST_FAIL, payload:error.message})
        }
   
  
  
}
// DETAILSPRODUCT
//we need to have a server in order to display the products
//it should get another link which contains the id of the product
const detailsProduct = (productId) => async(dispatch) => {
    try{
        dispatch({type: PRODUCT_DETAILS_REQUEST, payload: productId});
        fetch('http://localhost:5000/' + productId)
        .then(res=> res.json())
        .then(data=> dispatch({type: PRODUCT_DETAILS_SUCCESS, payload:data}) )
    }
    catch(error){
        dispatch({type: PRODUCT_DETAILS_FAIL, payload: error.message})
    }
}

// Filter products
const Filterproducts = (products,size) => (dispatch) => {
    return dispatch({
        type:FILTER_PRODUCTS_BY_SIZE,
        payload: {
            size:size,
            items:size === '' ? products : products.filter(a=> a.indexOf(size.toUpperCase()) >= 0)
        }
    })
}


export { listProduct, detailsProduct, Filterproducts }

代码 productReducers:

//two params are being accepted in the reducer func
    //* state 

import { 
    PRODUCT_DETAILS_FAIL,
    PRODUCT_DETAILS_REQUEST,
    PRODUCT_DETAILS_SUCCESS, 
    PRODUCT_LIST_FAIL, 
    PRODUCT_LIST_REQUEST, 
    PRODUCT_LIST_SUCCESS,
    FILTER_PRODUCTS_BY_SIZE,
    FILTER_PRODUCTS_BY_PRICE } from "../constants/productConstants";

    //*action
function producListReducer(state = {products: [], filteredItems: [], size: ''}, action){
    
    switch (action.type){
        // case is like the if statement
        //getting product
        case PRODUCT_LIST_REQUEST:
            return{loading: true};
            // when products are loaded
        case PRODUCT_LIST_SUCCESS:
            return{loading:false, products: action.payload};
            //when err occurs
        case PRODUCT_LIST_FAIL:
            return{loading: false, error: action.payload};
        case FILTER_PRODUCTS_BY_SIZE:
                return{...state, filteredItems: action.payload.items, size: action.payload.size}
        default:
                return state
    }
}

function productDetailsReducer(state = {product: {}}, action){
    
    switch (action.type){
        // case is like the if statement
        //getting product
        case PRODUCT_DETAILS_REQUEST:
            return{loading: true};
            // when products are loaded
        case PRODUCT_DETAILS_SUCCESS:
            return{loading:false, product: action.payload};
            //when err occurs
        case PRODUCT_DETAILS_FAIL:
            return{loading: false, error: action.payload};
        default:
                return state
    }
}







export { producListReducer,productDetailsReducer }

标签: javascriptnode.jsreactjsredux

解决方案


过滤器功能正常工作,但我不知道如何应用它。

搜索栏组件:

import React from 'react'


// Function Searchbar 
//Looks for products 

function Search(props){

   
    return(
     <input 
     type="search"
     className="search"
     placeholder={props.placeholder}
     onChange={props.handleInput}/>
    )
}

export default Search

产品成分:

return( // 在渲染产品之前检查加载 loading? loading... : error?{error}:

    {products.map(product=> (
    
        

    <li key={product.id} className="product"> 
     <Link to={"/product/" + product.id}><div className="img" style={{background: `url(${product.img})`, backgroundSize: 'cover'}}></div></Link>
           {/* LOOK OUT FOR TYPOS IN ROUTIING  dont put':' after /, this only applies
           when routing because the ": " implies for a parameter
           In this case you can directly access product.id  */}
       <Link to={"/product/" +  product.id}><h1>{product.name}</h1></Link> 
        <p> <small>€&lt;/small>{product.price}</p>
        <div>size: {product.size}</div>
      
        {product.qty > 0 ? <div><button onClick={handleAddToCart}>Add to cart</button>  <div>{product.qty} left</div></div> : <div>out of stock</div> }   
       
     
        
        </li> 
        )
        
        )}

         </ul>
        
         

)

Store.js 中的搜索栏功能:

import React,{Component, useState} from 'react'
import Product from '../components/product'
import Nav from '../components/nav'
import Footer from '../components/footer'
import Searchbar from '../components/searchbar'
import Filter from '../components/filter'


class Store extends Component{
   
    constructor(){
        super()
        this.state = {
            products: [],
            SearchProduct: ''
        }
    }
    componentDidMount(){
        fetch('http://localhost:5000/')
        .then(res=> res.json())
        .then(data=>this.setState({products:data}) )
       
    }
   
   render(){
       let filteredProducts = this.state.products.filter((product)=> {
            return product.name.toLowerCase().includes(this.state.SearchProduct.toLowerCase())
       })
    return (
        
        <div>
        <Nav/>
        <div className="store">

           
            <div className="title">
                <h1>Store</h1>
            </div>
            <aside>
                <Searchbar 
                placeholder="Search" 
                handleInput={(e)=> {
                   
                    this.setState({SearchProduct: e.target.value})
                }
                 
                } 
                />
                
                <ul>
                    <h2>Categories</h2>
                    <li>Women</li>
                    <li>Men</li>
                    <li>Clothing</li>
                    <li>Equipment</li>
                 
                </ul>
            </aside>
           
           <Filter/>
            
            <Product filter={filteredProducts}/>
            
         
           
        </div>
        <Footer/>
        </div>
    )
   }
   
}

export default Store

推荐阅读