Потеря выпадающего выбора опций при фильтрации с использованием API реагирования контекста - PullRequest
1 голос
/ 09 апреля 2020

Я только начал изучать React 2 недели go, поэтому я все еще нахожу некоторые концепции трудными. Я перешел от создания CRA к преобразованию его в Next JS и выбрал использование контекстного API с хуками для управления состоянием. Я сейчас работаю над фильтрацией списка статей, используя раскрывающийся список. Когда я выбираю статью определенного типа, список фильтруется корректно, но когда я go возвращаюсь к раскрывающемуся списку, там присутствует только оригинальная опция вместе с текущей. Когда я нажимаю на исходную опцию, все элементы списка исчезают. Я хочу предотвратить изменение параметров в раскрывающемся списке, а также разрешить фильтрацию работать в то же время, что и другие фильтры (например, фильтр сортировки по городу и фильтр по статье).

В моем коде Я борюсь с тем, чтобы выпадающий список рынков / рынков работал правильно.

Это мой контекст. js

import React, { useState, useReducer, createContext } from "react";
import { articles } from "./data";

// Create Context Object
const StateContext = React.createContext([{}, () => {}]);

// Create a provider for components to consume and subscribe to changes
const StateProvider = (props) => {
  const [state, setState] = useState({
    list: articles,
    market: "All",
    isLoading: true,
  });

  return (
    <StateContext.Provider value={[state, setState]}>
      {props.children}
    </StateContext.Provider>
  );
};

export { StateContext, StateProvider };

FilterControls. js:

import React from "react";

import useFilter from "../hooks/useFilter";

const Controls = () => {
  const { allEntries, market, handleChange } = useFilter();

  //   get all unique values
  const getUnique = (items, value) => {
    return [...new Set(items.map((item) => item[value]))];
  };
  let markets = getUnique(allEntries, "market");
  //   add all
  markets = ["All", ...markets];
  //   map to jsx
  markets = markets.map((item, index) => {
    return (
      <option value={item} key={index}>
        {item}
      </option>
    );
  });

  return (
    <>
      <div>
        <section className="filter-container">
          {/* select market */}
          <div className="form-group">
            <label htmlFor="market">Housing Market</label>
            <select
              name="market"
              id="market"
              value={market}
              className="form-control drop-down"
              onChange={handleChange}
            >
              {markets}
            </select>
          </div>
          {/* end of select market */}
        </section>

useFilter. js:

import { useContext } from "react";
import { StateContext } from "../context";

const StateFilter = () => {
  const [state, setState] = useContext(StateContext);

  let allEntries = formatData(state.list);
  let featuredEntries = allEntries.filter((e) => e.featured === true);
  let percentageOffMax = Math.max(
    ...allEntries.map((item) => item.percentageOff)
  );
  let avgppMax = Math.max(...allEntries.map((item) => item.avgpp));

  function formatData(items) {
    let tempItems = items.map((e) => {
      let id = e.id;
      let images = e.images;
      let singleEntry = { ...e, images, id };
      return singleEntry;
    });
    return tempItems.sort((a, b) => a.avgpp - b.avgpp);
  }

  function sortFromHighestToLowestPrices(items) {
    let tempItems = items.map((e) => {
      let id = e.id;
      let images = e.images;
      let singleEntry = { ...e, images, id };
      return singleEntry;
    });
    return tempItems.sort((a, b) => b.avgpp - a.avgpp);
  }
  let highestToLowest = sortFromHighestToLowestPrices(state.list);

  //   console.log(state.market);
  //   console.log(state);

  //   console.log(allEntries.filter((e) => e.market === "Homeowners"));
  function handleChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = event.target.name;

    console.log(value);
    let ftest = allEntries.filter((e) => e.market === value);

    setState((state) => ({ ...state, list: ftest, [name]: value }));

    // state.filterItems();
    // setState((state) =>({...state.market}))
    //   {
    //     [name]: value,
    //   },
    //   this.filterItems
    // );
    console.log(state);
  }
  // allEntries.filter((e) => e.market === value);

  function filterItems() {
    console.log(state.list);
    let { allEntries } = state.list;

    // let tempEntries = [...allEntries].sort((a, b) => b.avgpp - a.avgpp);
    // if (market !== "All") {
    //   tempEntries = tempEntries.filter((e) => e.market === market);
    // }
  }
  console.log(filterItems());

  return {
    isLoading: state.isLoading,
    allEntries,
    featuredEntries,
    sortedEntries: allEntries,
    percentageOff: percentageOffMax,
    percentageOffMax,
    avgppMax,
    handleChange,
    filterItems,
  };
};

export default StateFilter;

И статьи. js, где все отображается:

import React, { useContext } from "react";
import Entry from "../components/Entry";
import Title from "../components/Title";
import { StateContext } from "../context";

import FilterControls from "../components/FilterControls";
import useFilter from "../hooks/useFilter";

const FullList = () => {
  const { allEntries, showAdelphi, isLoading } = useFilter();
  return (
    <>
      <section className="all-entries">
        <Title title="Featured Entries" />
        <FilterControls />
        <div className="all-entries-center">
          {allEntries.map((e) => (
            <Entry key={e.id} entry={e} />
          ))}
        </div>
      </section>

1 Ответ

0 голосов
/ 11 апреля 2020

Причина, по которой это не работало, заключалась в том, что не было создано временного списка. Поэтому, когда был выбран элемент параметра, состояние заменялось на состояние, в котором не было другого элемента (элементов). Поскольку в раскрывающемся списке отображается состояние, параметры исчезают при уменьшении количества элементов в исходном списке.

Чтобы решить эту проблему, я вместо этого создал временный список, который будет корректироваться на основе фильтров устанавливается при сохранении исходного списка для справки.

Теперь отсортированный список отображает список на странице моих статей:

<section className="all-entries">
        <Title title="Featured Entries" />
        <FilterControls />
        <div className="all-entries-center">
          {state.sortedList.map((e) => (
            <Entry key={e.id} entry={e} />
          ))}
        </div>
      </section>

А теперь, в моем фильтре управления, рынки вытащены из исходного списка:

 let markets = getUnique(list, "market");
  //   add all
  markets = ["All", ...markets];
  //   map to jsx
  markets = markets.map((item, index) => {
    return (
      <option value={item} key={index}>
        {item}
      </option>
    );
  });
...