Search code examples
javascriptreactjsreduxreact-redux

Filter function does not work when I use Redux


I am currently using a small Shopping Cart project using React and Redux, Node I built the function for filtering products by size and Sort And it was working fine but when I used Redux the filtering process doesn't work anymore I tried it a lot

Store.js

import {createStore,compose,applyMiddleware} from 'redux'
import reducer from './Reducer/Reducer'
import reduxthunk from 'redux-thunk'

const initialState = {}
const enhancer = window.__REDUX_DEVTOOLS_EXTENTION_COMPOSE__ || compose
const store = createStore(reducer,initialState,enhancer(applyMiddleware(reduxthunk)))

export default store

Types.js

export const FETCH_PRODUCTS="FETCH_PRODUCTS"
export const FILTER_SIZE="FILTER_SIZE"
export const FILTER_SORT="FILTER_SORT"

ProductsActions.js

import { FETCH_PRODUCTS,FILTER_SIZE,FILTER_SORT} from './Types'

export const fetchProducts = () => {
    return (dispatch) => {
        fetch('/api/products').then(res => res.json()).then(data => {
            dispatch({
                type: FETCH_PRODUCTS,
                data: data
            })
        })
    }
}

export const filterdSize = (products,value) => {
    return (dispatch) => {
        let productClone = [...products]
        let newProduct = productClone.filter(p => p.size.indexOf(value) != -1)
        dispatch({
            type: FILTER_SIZE,
            data: {
                size: value,
                products: value == "ALL" ? products : newProduct
            }

        })
    }
}

export const filterdSort = (products, value) => {
    return (dispatch) => {
        let productClone = [...products];
        let newProduct = productClone.sort(function (a, b) {
            if (value == "lowest") {
                return a.price - b.price;
            } else if (value == "highest") {
                return b.price - a.price
            } else {
                return a.id < b.id ? 1 : -1
            }
        })
        dispatch({
            type:FILTER_SORT,
            data:{
                sort:value,
                products:newProduct
            }
        })
    }
}

ProductReducer.js

import {FETCH_PRODUCTS,FILTER_SIZE,FILTER_SORT} from '../Actions/Types'
const ProductReducer=(state={},action)=>{
    switch(action.type) {
        case FETCH_PRODUCTS:
            return {
                products:action.data,
                filterProducts:action.data
            }

        case FILTER_SIZE:
            return {
                ...state,
                size:action.data.size,
                filterProducts:action.data.products
            }

        case FILTER_SORT:
            return {
                ...state,
                sort: action.data.sort,
                filterProducts:action.data.products
            }

        default:
            return state
    }
}

export default ProductReducer

Reducer.js

import ProductReducer from './ProductReducer'
import {combineReducers} from 'redux'

export default combineReducers({
    products:ProductReducer
})

Filter.js

import React from 'react'
import './Filter.css'
import Flip from 'react-reveal/Flip';
import { connect } from 'react-redux'
import { filterdSize, filterdSort } from '../../store/Actions/Products'



const Filter = (props) => {
    return (
        <Flip left cascade>
            {props.filterProducts && <div className="filter-wrapper">
                <h2 className="filter-title">Filter</h2>
                <div className="nom-of-product">number of product {props.filterProducts.length} </div>
                <div className="filter-by-size">
                    <span className="span-title">Size</span>
                    <select className="filter-select" onChange={(e) => filterdSize(props.products, e.target.value)} value={props.size}>
                        <option value="ALL">ALL</option>
                        <option value="S">S</option>
                        <option value="M">M</option>
                        <option value="L">L</option>
                        <option value="XL">XL</option>
                        <option value="XXL">XXL</option>
                    </select>
                </div>
                <div className="filter-by-size">
                    <span className="span-title">Order</span>
                    <select className="filter-select" onChange={(e) => filterdSort(props.filterProducts, e.target.value)} value={props.sort}>
                        <option value="lastes">Lastes</option>
                        <option value="lowest">Lowest</option>
                        <option value="highest">Highest</option>
                    </select>
                </div>
            </div>}
        </Flip>
    )
}

export default connect((state) => {
    return {
        sort: state.products.sort,
        size: state.products.size,
        products: state.products.products,
        filterProducts: state.products.filterProducts
    }
}, { filterdSize, filterdSort })(Filter)

Solution

  • You should dispatch your actions, not just call them, so you would want to get dispatch function using useDispatch from react-redux

    const dispatch = useDispatch();
    

    And then call your actions with dispatch, for example:

    onChange={(e) => dispatch(filterdSize(props.products, e.target.value))}