admin管理员组

文章数量:1026989

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>
  </>
);

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>
  </>
);

本文标签: javascriptSearch filter does not work across the reacttable on setStateReact JSStack Overflow