首页 > 解决方案 > 尝试通过 react-redux 中的产品名称列表进行过滤

问题描述

我正在尝试通过产品列表过滤用户输入。
当用户删除他们的输入时,我正在尝试实现一个过滤器跟踪器来查看用户是否这样做,以便数组相应地更新。
我不知道我的逻辑有什么问题,但我无法获得返回的过滤值来渲染,而是获得了初始状态值。

https://codesandbox.io/s/redux-ing-j4igf?file=/src/Redux.js

index.js:

import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import { reducer } from "./Redux";
import AppWrapper from "./AppWrapper";

const store = createStore(reducer);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Provider store={store}>
    <AppWrapper />
  </Provider>,
  rootElement
);

AppWrapper.js:

 import { connect } from "react-redux";
import App from "./App";
import { getInputValue } from "./Redux";

const mapStateToProps = (state) => ({
  searchString: state.searchString,
  productData: state.productData,
  filteredProducts: state.filteredProducts
});

const mapDispatchToProps = (dispatch) => {
  return {
    filterByValue: (e) => {
      let input = e.target.value;
      dispatch(getInputValue({ value: input }));
    },
    triggerUserValue: () => {
      dispatch({ type: "TRIGGER_USER_VALUE" });
    }
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

应用程序.js:

import "./styles.css";
import TemplateCard from "./TemplateCard";
import React from "react";

class App extends React.Component {
  render() {
    let products = this.props.productData;
    return (
      <div className="App">
        <div className="flex">
          <input
            placeholder="filter items"
            onChange={this.props.filterByValue}
          />
          <button onClick={this.props.triggerUserValue}> click me </button>
        </div>
        <div className="flex">
          {products.map((i) => {
            return (
              <TemplateCard
                key={i.id}
                title={i.title}
                text={i.text}
                price={i.price}
                imageurl={i.imageurl}
              />
            );
          })}
        </div>
      </div>
    );
  }
}

export default App;

Redux.js:

export const initialState = {
  searchString: "",
  anotherthingy: "",
  productData: [
    {
      id: 1,
      name: "Roses",
      title: "Roses",
      text: "Beautiful hand picked roses fresh out of our gardins",
      price: 9.99
    },
    {
      id: 2,
      name: "Dahlia",
      title: "Dahlia",
      text: "Beautiful hand picked Dahlia fresh out of our gardins",
      price: 17.99
    },
    {
      id: 3,
      name: "Alstroemerias",
      title: "Alstroemerias",
      text: "Beautiful hand picked Alstroemerias fresh out of our gardins",
      price: 12.99
    },
    {
      id: 4,
      name: "Calla lillies",
      title: "Calla lillies",
      text: "Beautiful hand picked Calla lillies fresh out of our gardins",
      price: 16.99
    }
  ],
  appliedFilters: []
};

const FILTER_BY_VALUE = "FILTER_BY_VALUE";

export const getInputValue = (payload) => {
  return {
    type: FILTER_BY_VALUE,
    payload
  };
};

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case FILTER_BY_VALUE:
      let newState = Object.assign({}, state);
      let value = action.payload.value;
      let filteredValues = state.productData.filter((product) => {
        return product.name.toLowerCase().includes(value);
      });
      console.log(filteredValues);

      let appliedFilters = state.appliedFilters;
      if (value === true) {
        let index = appliedFilters.indexOf(FILTER_BY_VALUE);
        if (index === -1) appliedFilters.push(FILTER_BY_VALUE);
        newState.productData = filteredValues;
      } else {
        let index = appliedFilters.indexOf(FILTER_BY_VALUE);
        appliedFilters.splice(index, 1);
        if (appliedFilters.length === 0) {
          newState.filteredProducts = newState.productData;
        }
      }
      console.log(newState);
      return { ...newState, productData: newState.filteredProducts };

    case "TRIGGER_USER_VALUE":
      alert(state.searchString);
      return state;
    default:
      return state;
  }
};

标签: reactjsreduxreact-redux

解决方案


In your reducer, update code for FILTER_BY_VALUE action like below:-

case FILTER_BY_VALUE:
      let newState = Object.assign({}, state);
      let value = action.payload.value;
      let filteredValues = state.productData.filter((product) => {
        return product.name.toLowerCase().includes(value);
      });

      let appliedFilters = state.appliedFilters;
      if (value) {
        let index = appliedFilters.indexOf(FILTER_BY_VALUE);
        if (index === -1) appliedFilters.push(FILTER_BY_VALUE);
        newState.filteredProducts = filteredValues;  // changed here to store in filteredProducts
      } else {
        let index = appliedFilters.indexOf(FILTER_BY_VALUE);
        appliedFilters.splice(index, 1);
        if (appliedFilters.length === 0) {
          newState.filteredProducts = initialState.productData; // get initial productData if there are no filters
        }
      }
      console.log(newState);
      return { ...newState, productData: newState.filteredProducts }; // set productData

推荐阅读