最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Search filter does not work across the react-table on setState : React JS - Stack Overflow

matteradmin7PV0评论

I am using react-table for data grid purposes. All I am trying to implement a search filter that searches data across the table and filters down by using filter method. I have maintained a separate ponent for Searching and I set the table's data inside search ponent. The filtering breaks when the characters are being deleted from the search filter. Am I doing something wrong here.

Sandbox:

SearchComponent

import React from "react";
import { Input } from "semantic-ui-react";

export default class GlobalSearchComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      filteredData: [],
      searchInput: ""
    };
  }

  handleChange = event => {
    this.setState({ searchInput: event.target.value }, () =>
      this.globalSearch()
    );
  };

  globalSearch = () => {
    let { searchInput } = this.state;
    let filteredData = this.props.data.filter(value => {
      return (
        value.firstName.toLowerCase().includes(searchInput.toLowerCase()) ||
        value.status.toLowerCase().includes(searchInput.toLowerCase()) ||
        value.visits
          .toString()
          .toLowerCase()
          .includes(searchInput.toLowerCase())
      );
    });
    this.props.handleSetData(
      (filteredData.length > 0 && filteredData) || searchInput
        ? filteredData
        : this.props.data
    );
  };

  render() {
    return (
      <>
        <br />
        <Input
          size="large"
          name="searchInput"
          value={this.state.searchInput || ""}
          onChange={this.handleChange}
          label="Search"
        />
        <br />
        <br />
      </>
    );
  }
}

App Component

import React from "react";
import ReactDOM from "react-dom";
import GlobalSearchComponent from "./GlobalSearchComponent";
import ReactTable from "react-table";
import "react-table/react-table.css";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
      columns: [],
      searchInput: ""
    };
  }

  ponentDidMount() {
    this.getData();
    this.getColumns();
  }

  getColumns = () => {
    let columns = [
      {
        Header: "First Name",
        accessor: "firstName"
      {
        Header: "Status",
        accessor: "status"
      },
      {
        Header: "Visits",
        accessor: "visits"
      }
    ];
    this.setState({ columns });
  };

  getData = () => {
    let data = [
      { firstName: "aaaaa", status: "Pending", visits: 155 },
      { firstName: "aabFaa", status: "Pending", visits: 155 },
      { firstName: "adaAAaaa", status: "Approved", visits: 1785 },
      { firstName: "aAaaaa", status: "Approved", visits: 175 },
      { firstName: "adaSaaa", status: "Cancelled", visits: 165 },
      { firstName: "aasaaa", status: "Cancelled", visits: 157 },
      { firstName: "aweaaaaaewea", status: "Approved", visits: 153 },
      { firstName: "adaAAadsdweaa", status: "Approved", visits: 17585 },
      { firstName: "aAaaaa", status: "Approved", visits: 175 }
    this.setState({ data });
  };

  handleSetData = data => {
    console.log(data);
    this.setState({ data });
  };

  render() {
    let { data, columns } = this.state;
    return (
      <div>
        <GlobalSearchComponent
          data={this.state.data}
          handleSetData={this.handleSetData}
        />
        <ReactTable
          data={data}
          columns={columns}
          defaultPageSize={10}
          className="-striped -highlight"
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I am using react-table for data grid purposes. All I am trying to implement a search filter that searches data across the table and filters down by using filter method. I have maintained a separate ponent for Searching and I set the table's data inside search ponent. The filtering breaks when the characters are being deleted from the search filter. Am I doing something wrong here.

Sandbox: https://codesandbox.io/s/stoic-gould-kw9iq

SearchComponent

import React from "react";
import { Input } from "semantic-ui-react";

export default class GlobalSearchComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      filteredData: [],
      searchInput: ""
    };
  }

  handleChange = event => {
    this.setState({ searchInput: event.target.value }, () =>
      this.globalSearch()
    );
  };

  globalSearch = () => {
    let { searchInput } = this.state;
    let filteredData = this.props.data.filter(value => {
      return (
        value.firstName.toLowerCase().includes(searchInput.toLowerCase()) ||
        value.status.toLowerCase().includes(searchInput.toLowerCase()) ||
        value.visits
          .toString()
          .toLowerCase()
          .includes(searchInput.toLowerCase())
      );
    });
    this.props.handleSetData(
      (filteredData.length > 0 && filteredData) || searchInput
        ? filteredData
        : this.props.data
    );
  };

  render() {
    return (
      <>
        <br />
        <Input
          size="large"
          name="searchInput"
          value={this.state.searchInput || ""}
          onChange={this.handleChange}
          label="Search"
        />
        <br />
        <br />
      </>
    );
  }
}

App Component

import React from "react";
import ReactDOM from "react-dom";
import GlobalSearchComponent from "./GlobalSearchComponent";
import ReactTable from "react-table";
import "react-table/react-table.css";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
      columns: [],
      searchInput: ""
    };
  }

  ponentDidMount() {
    this.getData();
    this.getColumns();
  }

  getColumns = () => {
    let columns = [
      {
        Header: "First Name",
        accessor: "firstName"
      {
        Header: "Status",
        accessor: "status"
      },
      {
        Header: "Visits",
        accessor: "visits"
      }
    ];
    this.setState({ columns });
  };

  getData = () => {
    let data = [
      { firstName: "aaaaa", status: "Pending", visits: 155 },
      { firstName: "aabFaa", status: "Pending", visits: 155 },
      { firstName: "adaAAaaa", status: "Approved", visits: 1785 },
      { firstName: "aAaaaa", status: "Approved", visits: 175 },
      { firstName: "adaSaaa", status: "Cancelled", visits: 165 },
      { firstName: "aasaaa", status: "Cancelled", visits: 157 },
      { firstName: "aweaaaaaewea", status: "Approved", visits: 153 },
      { firstName: "adaAAadsdweaa", status: "Approved", visits: 17585 },
      { firstName: "aAaaaa", status: "Approved", visits: 175 }
    this.setState({ data });
  };

  handleSetData = data => {
    console.log(data);
    this.setState({ data });
  };

  render() {
    let { data, columns } = this.state;
    return (
      <div>
        <GlobalSearchComponent
          data={this.state.data}
          handleSetData={this.handleSetData}
        />
        <ReactTable
          data={data}
          columns={columns}
          defaultPageSize={10}
          className="-striped -highlight"
        />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Share Improve this question edited Jul 2, 2019 at 9:24 joy08 asked Jul 2, 2019 at 8:50 joy08joy08 9,6629 gold badges42 silver badges81 bronze badges 1
  • why value={this.state.searchInput || ""}? – Junius L Commented Jul 2, 2019 at 8:54
Add a ment  | 

2 Answers 2

Reset to default 2

Don't update the original data, update filtered data in your main app.

SearchComponent

remove filteredData[] from state, and change global search to

globalSearch = () => {
  let { searchInput } = this.state;
  let filteredData = this.props.data.filter(value => {
    return (
      value.firstName.toLowerCase().includes(searchInput.toLowerCase()) ||
      value.status.toLowerCase().includes(searchInput.toLowerCase()) ||
      value.visits
        .toString()
        .toLowerCase()
        .includes(searchInput.toLowerCase())
    );
  });

  this.props.handleSetData(filteredData);

};

App Component

change handleSetData to update filteredData instead of data.

handleSetData = data => {
  console.log(data);
  this.setState({ filteredData: data });
};

getData = () => {

  let data = [...]

  this.setState({ data, filteredData: data });
};

// change your render to 

render() {
  let { filteredData, columns } = this.state;
  return (
    <div>
      <GlobalSearchComponent
        data={this.state.data}
        handleSetData={this.handleSetData}
      />
      <ReactTable
        data={filteredData}
        columns={columns}
        defaultPageSize={10}
        className="-striped -highlight"
      />
    </div>
  );
}

DEMO

In react-table v7+ you can use useGlobalFilter here's how to do it.

import React, { useMemo } from 'react';
import { useGlobalFilter, useTable } from 'react-table';

// sample array
import users from 'mock/users';

boilerplate setup

const data = useMemo(() => users, []);

const columns = useMemo(
  () => [
    {
      Header: 'Name',
      accessor: 'name',
    },
    {
      Header: 'Email',
      accessor: 'email',
    },
  ],
  []
);

const {
  getTableProps,
  getTableBodyProps,
  headerGroups,
  rows,
  prepareRow,
  setGlobalFilter,
} = useTable({
  columns,
  data
},
  useGlobalFilter,
);

render the html

return (
  <>
    <input
      type="search"
      placeholder="Search"
      onChange={(e) => setGlobalFilter(e.target.value ? e.target.value : undefined)}
    />

    <table {...getTableProps({ role: null })}>
      <thead>
        {headerGroups.map((headerGroup) => (
          <tr {...headerGroup.getHeaderGroupProps({ role: null })}>
            {headerGroup.headers.map((column) => (
              <th {...column.getHeaderProps()} >
                {column.render('Header')}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps({ role: null })}>
        {rows.map((row) => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps({ role: null })}>
              {row.cells.map((cell) => <td {...cell.getCellProps({ role: null })} >
                {cell.render('Cell')}
              </td>)}
            </tr>
          );
        })}
      </tbody>
    </table>
  </>
);
Post a comment

comment list (0)

  1. No comments so far