如何在ReactJS项目中应用redux-toolkit中的filters属性

ws51t4hk  于 2022-11-24  发布在  React
关注(0)|答案(1)|浏览(173)

x1c 0d1x我想在我的购物车网站过滤属性。我在这里使用redux工具包在我的ReactJS项目。我显示的产品。我在这里使用(https://dummyjson.com/products)API在我的项目中列出我的产品。我想应用类别和价格的过滤器属性。我试过了,但过滤功能不适用。请帮助我如何在redux中应用和制作过滤器属性-下面是代码的所有文件。
productSlice.js

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
const baseURL = "https://dummyjson.com/products";
export const STATUSES = Object.freeze({
  IDLE: "idle",
  ERROR: "error",
  LOADING: "loading",
});

export const fetchProducts = createAsyncThunk(
  "products/fetch",
  async () => {
    const res = await axios.get(baseURL);
    const data = await res.data;
    return data;
  }
);

export const getProduct = createAsyncThunk(
  "product/getProduct",
  async (id, { rejectWithValue }) => {
    try {
      const response = await axios.get(`${baseURL}/${id}`);
      return response.data;
    } catch (error) {
      return rejectWithValue(error.response);
    }
  }
);



const productSlice = createSlice({
  name: "product",
  initialState: {
    products: [],
    product: {},
    status: STATUSES.IDLE,
  },
  reducers: {
   
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchProducts.pending, (state, action) => {
        state.status = STATUSES.LOADING;
      })
      .addCase(fetchProducts.fulfilled, (state, action) => {
        state.products = action.payload;
        state.status = STATUSES.IDLE;
      })
      .addCase(fetchProducts.rejected, (state, action) => {
        state.status = STATUSES.ERROR;
      })
      .addCase(getProduct.pending, (state, action) => {
        state.status = STATUSES.LOADING;
      })

      .addCase(getProduct.fulfilled, (state, action) => {
        state.status = STATUSES.IDLE;
        state.product = action.payload;
      });
  },
});

export const { handlePriceFilter } = productSlice.actions;
export default productSlice.reducer;

Home.js

import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Products, SearchBar } from "../components";
import Filters from "../components/Filters";
import { fetchProducts, STATUSES } from "../redux/features/productSlice";
import { FaFilter } from "react-icons/fa";
import SidebarFilterPanel from "../components/SidebarFilterPanel";
const categories = [
  "Smartphones",
  "Laptops",
  "Fragrances",
  "Skincare",
  "Groceries",
  "Home-Decoration",
];
const Home = () => {
  const dispatch = useDispatch();
  const { products, status } = useSelector((state) => state.product.products);

  const [openFilter, setOpenFilter] = useState(false);
  const openFilterPanel = () => setOpenFilter(!openFilter);

  useEffect(() => {
    dispatch(fetchProducts());
  }, []);

  useEffect(() => {
    document.title = "Shoping Website";
  }, []);

  return (
    <div>
      <div className="flex gap-4 justify-between px-4">
        <div className="hidden md:block">
          <Filters categories={categories} />
        </div>
        <div className="flex flex-col items-center justify-center w-full">
          <div className="flex items-center">
            <SearchBar />
            <div
              onClick={openFilterPanel}
              className={`bg-black text-white py-[10px] px-3 md:hidden block rounded cursor-pointer ml-2 mt-3 duration-1000 transition-all`}
            >
              <FaFilter onClick={openFilterPanel} />
            </div>

            {openFilter && <SidebarFilterPanel categories={categories} />}
          </div>
          <div className="grid gap-4 lg:grid-cols-4 sm:grid-cols-2 grid-cols-1 place-items-center mr-auto ml-auto w-full mt-4">
            {products &&
              products?.map((product) => (
                <Products key={product.id} product={product} />
              ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default Home;

Filters.js

import React, { useRef } from "react";
import Slider from "@mui/material/Slider";

import { useDispatch } from "react-redux";
const Filters = ({categories}) => {
  const dispatch = useDispatch();

  return (
    <div className=" w-[200px] shadow-lg h-[600px] flex flex-col px-2 py-10">
      <div className="w-[150px] ml-auto mr-auto flex flex-col gap-2">
        <p className="font-bold">Price</p>
        <Slider
          valueLabelDisplay="auto"
          aria-labelledby="range-slider"
          min={0}
          max={1500}
        />
      </div>

      <div className="px-2 mt-6">
        <p className="font-bold mb-2">Catogries</p>
        {categories.map((category, index) => (
          <p
            className="cursor-pointer text-sm my-2 hover:text-orange-500"
            key={index}
            // onClick={() => handleSelectCategory(category)}
          >
            {category}
          </p>
        ))}
      </div>

      <div className="w-[150px] ml-auto mr-auto flex flex-col gap-2 my-8">
        <p className="font-bold">Discount</p>
        <Slider
          valueLabelDisplay="auto"
          aria-labelledby="range-slider"
          min={0}
          max={30}
        />
      </div>

      <div className="w-[150px] ml-auto mr-auto flex flex-col gap-2 mt-8">
        <p className="font-bold">Rating</p>
        <Slider

          valueLabelDisplay="auto"
          aria-labelledby="range-slider"
          min={0}
          max={5}
        />
      </div>
    </div>
  );
};

export default Filters;
e0uiprwp

e0uiprwp1#

您可以通过创建另一个状态切片来保存筛选器类别及其值来实现这一点。使用产品数组和筛选器值,并在呈现时内联筛选产品。
1.创建过滤器切片并添加到存储区
filter.slice.js

import { createSlice } from "@reduxjs/toolkit";

const filterSlice = createSlice({
  name: "filters",
  initialState: {
    price: 1500
  },
  reducers: {
    setPriceFilter: (state, action) => {
      state.price = Math.max(0, action.payload);
    }
  }
});

export const actions = {
  ...filterSlice.actions
};

export default filterSlice.reducer;

store.js

import { configureStore } from "@reduxjs/toolkit";
import productReducer from "./features/productSlice";
import cartReducer from "./features/cartSlice";
import filtersReducer from "./features/filter.slice";

export const store = configureStore({
  reducer: {
    cart: cartReducer,
    filters: filtersReducer,
    product: productReducer
  }
});

1.更新Filter组件以使用筛选器值并将更新调度到存储区。

import React from "react";
import Slider from "@mui/material/Slider";
import { useDispatch, useSelector } from "react-redux";
import { actions as filtersActions } from "../redux/features/filter.slice";

const Filters = ({ categories }) => {
  const dispatch = useDispatch();
  const price = useSelector((state) => state.filters.price);

  return (
    <div className=" w-[200px] shadow-lg h-[600px] flex flex-col px-2 py-10">
      <div className="w-[150px] ml-auto mr-auto flex flex-col gap-2">
        <p className="font-bold">Price</p>
        <Slider
          valueLabelDisplay="auto"
          aria-labelledby="range-slider"
          min={0}
          max={1500}
          value={price}
          onChange={(e, value) =>
            dispatch(filtersActions.setPriceFilter(value))
          }
        />
      </div>

      ...
    </div>
  );
};

export default Filters;

1.在Home组件中呈现时,内联筛选products数组。

const Home = () => {
  const dispatch = useDispatch();
  const { products, status } = useSelector((state) => state.product.products);
  const { price } = useSelector((state) => state.filters);

  const [openFilter, setOpenFilter] = useState(false);
  const openFilterPanel = () => setOpenFilter(!openFilter);

  useEffect(() => {
    dispatch(fetchProducts());
  }, []);

  useEffect(() => {
    document.title = "Shoping Website";
  }, []);

  return (
    <div>
      <div className="flex gap-4 justify-between px-4">
        <div className="hidden md:block">
          <Filters categories={categories} />
        </div>
        <div className="flex flex-col items-center justify-center w-full">
          ...
          <div className="grid gap-4 lg:grid-cols-4 sm:grid-cols-2 grid-cols-1 place-items-center mr-auto ml-auto w-full mt-4">
            {products
              ?.filter((product) => product.price <= price)
              .map((product) => (
                <Products key={product.id} product={product} />
              ))}
          </div>
        </div>
      </div>
    </div>
  );
};

相关问题