Use Buttons to trigger filter function on react-table in React Use Buttons to trigger filter function on react-table in React reactjs reactjs

Use Buttons to trigger filter function on react-table in React


For React-Table filter to be controlled externally by buttons, you should take a look at the Controlled Table example. Then the table component becomes a controlled component.

There, you can set the state of the table filter externally and use both of the props:

<ReactTable  ...(your other props)        filtered={this.state.filtered}        onFilteredChange={filtered => this.setState({ filtered })} />

The filtered prop will monitor change in the state. So whenever you update its value through your letter buttons via e.g.

this.setState({filtered: { id: "dName", value: "A"}})

the table's filter will get updated. Also, onFilteredChange should work the other direction, namely the embedded filtering of the react-table can update the local state. So that you can monitor it and use its value within your DataGrid component.

One other option could be to avoid using local states and implement it in redux, though. Because states hanging around components are eventually becoming source of errors and increasing complexity of debugging.

UPDATE -- As per the question owner's comment for more details:

In order to use FilterButtons and DataGrid together, you can define a container component that encapsulates both FilterButtons and DataGrid. The container component keeps the shared state, and the filtering function operates on the state function. But data will still reside within the datagrid.

class DataGridWithFilter extends React.Component {// you need constructor() for binding alphaFilter to this. // otherwise it cannot call this.setStateconstructor(props) {   super(props);   this.alphaFilter = this.alphaFilter.bind(this);}// personally i do not use ids for passing data. // therefore introduced the l parameter for the letteralphaFilter(e,l) {  console.log(e.target.id);  this.setState({filtered: { id: "dName", value: l}});} render(){   return <div>      <DataGrid filtered={this.state.filtered}                 filterFunc={this.alphaFilter}      </DataGrid>      <BottomMenu filtered={this.state.filtered}                  filterFunc={this.alphaFilter} />   </div> }}

Also this above thing requires the use of prop filterFunc from within BottomMenu and FilterButtons components.

class FilterButtons extends React.Component {render() { const {props} =  this; return (    <div>       <button onClick={(e) => props.filterFunc(e, "A")} id="A" className="letter">A</button>       <button onClick={(e) => props.filterFunc(e, "B")} id="B" className="letter">B</button>       <button onClick={(e) => props.filterFunc(e, "C")} id="C" className="letter">C</button>    </div>  ); }}const BottomMenu = props => (  <div className="btm-menu">  <div className="toprow">  <div className="filter-keys">    <FilterButtons filterFunc = {props.filterFunc} />  </div></div></div>); class DataGrid extends React.Component {  constructor() {    super();    this.state = {      data: [],    };  }  componentWillMount() {    fetch('http://localhost:3000/rooms.json').then((results) => results.json()).then((data) => {        console.log(data.room);        this.setState({          data: data.room        })      })  }  render() {    const { data } = this.state;    return (      <div>        <ReactTable          data={data}          filterable          defaultFilterMethod={(filter, row) =>            String(row[filter.id]) === filter.value}          columns={[                {                  Header: "Name",                  accessor: "dName",                  filterMethod: (filter, row) =>                    row[filter.id].startsWith(filter.value)                },                {                  Header: "Department",                  accessor: "dDept"                },                {                  Header: "Room",                  accessor: "dRoom"                },                {                  Header: "Map",                  accessor: "dRoom",                  id: "over",                }              ]            }          defaultPageSize={14}          className="-striped -highlight"          filtered = {this.props.filtered}          onFilteredChange = {filtered => this.props.filterFunc({filtered})}        />        <br />       </div>    );  }}

I have not checked against typo etc but this should work.


In React, you can update components when state changes. The only way to trigger is to use this.setState()

So I would change my state object something like this:

state = {  date: [],  filter: ""};

so here is the new file:

// In Directory.jsclass FilterButtons extends React.Component {alphaFilter = (word) => {  this.setState({    filter: word  });};render() { return (    <div>       <button onClick={() => this.alphaFilter("A")} id="A" className="letter">A</button>       <button onClick={() => this.alphaFilter("B")} id="B" className="letter">B</button>       <button onClick={() => this.alphaFilter("C")} id="C" className="letter">C</button>    </div>  ); }}const BottomMenu = props => (  <div className="btm-menu">  <div className="toprow">  <div className="filter-keys">    <FilterButtons />  </div></div></div>);

right after you call alphaFilter() your component will update. And when you put your filter function in it it's going display as expected. So I would choose the .map() function of array. You can either use filter() or return after comparing data in map()


For react-table 7 you can listen for input changes outside and call setFilter:

useEffect(() => {  // This will now use our custom filter for age  setFilter("age", ageOutside);}, [ageOutside]);

See https://codesandbox.io/s/react-table-filter-outside-table-bor4f?file=/src/App.js