Swan
Swan

Reputation: 13

Multiple Filtering in React table without libraries (React-table) with react-hooks

I have a filters by id and by firstName - but how can I use them together? How can I use 3-4-5 filters together that are related to each other? When I clear the filter - them doesn't work correctly How can I get the result of first filter when I clear the second and vice versa. What is the best practice?

table view: table view

    import React, { useState, useEffect, useCallback, useMemo } from "react";
    import BootstrapTable from "./BootstrapTable";
    import useFetchHook from "../useFetchHook";

    export default function BootstrapTableContainer() {
    const [filterValue, setFilterValue] = useState("");
    const [idFilter, setIdFilter] = useState("all");
    const [firstNameFilter, setFirstNameFilter] = useState("");
    const [data, loading, error, setError] = useFetchHook(
    `http://www.filltext.com/?rows=${20}&id={number|1000}&firstName={firstName}&lastName={lastName}&email={email}&category=[1,2]&phone={phone|(xxx)xxx-xx-xx}&address={addressObject}&description={lorem|32}`,
    []
  );
  const [dataTable, setDataTable] = useState(data);

  const setFilterId = useCallback((value) => {
    setIdFilter(value);
  }, [setIdFilter]);

  const setFilterFirstName = useCallback((value) => {
    setFirstNameFilter(value);
  }, [setFirstNameFilter]);


  useEffect(() => {
    let newData;
    switch (idFilter) {
      case "all":
        newData = [...dataTable];
        break;
      case "0":
        newData = dataTable.filter((obj) => {
          return obj.id >= 0 && obj.id < 300;
        });
        break;
      case "300":
        newData = dataTable.filter((obj) => {
          return obj.id >= 300 && obj.id < 600;
        });
        break;
      case "600":
        newData = dataTable.filter((obj) => {
          return obj.id >= 600 && obj.id <= 1000;
        });
        break;
      default:
        break;
    }
    if (!firstNameFilter) {
       newData = [...newData]
    } else {
       newData = newData.filter((obj) => {
        return obj.firstName
          .toLowerCase()
          .includes(firstNameFilter.toLowerCase());
      });

    }
    setDataTable(newData);
  }, [idFilter, setDataTable, firstNameFilter]);


  const bootstrapTable = useMemo(() => {
    return (
      <BootstrapTable
        idFilter={idFilter}
        setFilterId={setFilterId}
        firstNameFilter={firstNameFilter}
        setFilterFirstName={setFilterFirstName}
        data={dataTable}
      />
    );
  }, [dataTable, idFilter, setFilterId, firstNameFilter, setFilterFirstName]);



  return (
    <div>
      {bootstrapTable}
    </div>
  );
}

Upvotes: 0

Views: 1493

Answers (1)

Pavel Petrovich
Pavel Petrovich

Reputation: 764

You have so simple state properties to solve your problem. I'll write some ideas to youo

import React, { useState, useEffect, useCallback, useMemo } from "react";
import BootstrapTable from "./BootstrapTable";
import useFetchHook from "../useFetchHook";

const filterById = (dataTable, value) => {
  switch (value) {
    case "0":
      return dataTable.filter((obj) => {
        return obj.id >= 0 && obj.id < 300;
      });

    case "300":
      return dataTable.filter((obj) => {
        return obj.id >= 300 && obj.id < 600;
      });

    case "600":
      return dataTable.filter((obj) => {
        return obj.id >= 600 && obj.id <= 1000;
      });

    case "all":
      return [...dataTable];
  }
};

export default function BootstrapTableContainer() {
  const [filters, setFilters] = useState([]);
  const [data, loading, error, setError] = useFetchHook(
    `http://www.filltext.com/?rows=${20}&id={number|1000}&firstName={firstName}&lastName={lastName}&email={email}&category=[1,2]&phone={phone|(xxx)xxx-xx-xx}&address={addressObject}&description={lorem|32}`,
    []
  );
  const [dataTable, setDataTable] = useState(data);

  useEffect(() => {
    let newData = dataTable;
    filters.forEach(({ name, value }) => {
      switch (name) {
        // here we filter by id
        case "id":
          newData = filterById(newData, value);
          break;

        // here we filter by firstname
        case "firstname":
          // newData = filterByFirstName(newData, value);
          break;

        // ...

        default:
          break;
      }
    });
    setDataTable(newData);
  }, [filters]);

  const bootstrapTable = useMemo(() => {
    return (
      <BootstrapTable
        filters={filters}
        handleFilterChandge={(e) => {
          // e - input event onChange:
          // <input name="firstname"
          //   onChange={props.handleFilterChandge}
          //   value={props.filters.firstname} 
          // />
          // 
          setFilters([
            ...filters,
            { name: e.target.name, value: e.target.value },
          ]);
        }}
        data={dataTable}
      />
    );
  }, [dataTable, filters]);

  return <div>{bootstrapTable}</div>;
}

Upvotes: 1

Related Questions