使用按钮在 React 中的 react-table 上触发过滤功能

Posted

技术标签:

【中文标题】使用按钮在 React 中的 react-table 上触发过滤功能【英文标题】:Use Buttons to trigger filter function on react-table in React 【发布时间】:2018-07-15 18:29:26 【问题描述】:

我不知道该怎么说。我正在学习 React,我通过 fetch 将数据加载到 React-Table 中。我尝试使用 React-Table 和自定义普通 div 和表格。

我想从 A、B、C、D ... Z 创建一个字母表的触摸按钮。这些按钮应该为按钮中的字母调用过滤器。因此,例如,按钮如下。

// In Directory.js
class FilterButtons extends React.Component 

alphaFilter(e) 
  console.log(e.target.id);
  // somehow filter the react table


render() 

 return (
    <div>
       <button onClick=this.alphaFilter id="A" className="letter">A</button>
       <button onClick=this.alphaFilter id="B" className="letter">B</button>
       <button onClick=this.alphaFilter 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>
);

// 我有一个类目录扩展组件,其中包含底部菜单

// 我还有一个 DataGrid.js,里面有 React 表

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"
        />
        <br />

      </div>
    );
  


export default DataGrid; 

此时我不确定该怎么做才能让按钮单击 A、B、C 字母之一来过滤 React 表。我不想要始终使用的输入字段选项,因为我只想要按钮,因为用户没有键盘,只有触摸。

基本上,React Table 或任何可以通过单击带有传递回过滤器的字母的按钮来过滤的表。如果我使用的是 JQuery,我会使用按钮单击,然后以这种方式过滤。我仍然没有了解 React 的所有细节以及如何完成这项工作。我也想使用外部按钮进行排序,但希望这样会更容易。

谢谢。 抱歉,如果所有这些都没有意义,我只是想把它摆出来。同样,没有键盘,只能触摸触摸屏,所以输入字段对我不起作用。

【问题讨论】:

你还有这个问题吗? 【参考方案1】:

要通过按钮从外部控制 React-Table 过滤器,您应该查看Controlled Table 示例。那么表格组件就变成了controlled component.

在那里,您可以在外部设置表格过滤器的状态并使用这两个道具:

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

filtered 属性将监控状态的变化。因此,每当您通过字母按钮更新其值时,例如

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

表格的过滤器将得到更新。此外,onFilteredChange 应该工作在另一个方向,即 react-table 的嵌入式过滤可以更新本地状态。这样您就可以监控它并在您的 DataGrid 组件中使用它的值。

不过,另一种选择可能是避免使用本地状态并在 redux 中实现它。因为围绕组件的状态最终会成为错误的来源并增加调试的复杂性。

更新——根据问题所有者的评论了解更多详情:

为了同时使用FilterButtons 和DataGrid,您可以定义一个容器组件来封装FilterButtons 和DataGrid。 容器组件保持共享状态,过滤函数对状态函数进行操作。但数据仍将驻留在数据网格中。

class DataGridWithFilter extends React.Component 

// you need constructor() for binding alphaFilter to this. 
// otherwise it cannot call this.setState
constructor(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 letter
alphaFilter(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>
 

此外,上述内容需要在 BottomMenu 和 FilterButtons 组件中使用 prop filterFunc

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

我没有检查错字等,但这应该可以。

【讨论】:

谢谢。我正在调查,我会报告。 谢谢。我试图实现这一点,并且 onclick 过滤似乎没有更新反应表。我可能会尝试让他的代码笔或其他东西。你能解释一下 redux 选项吗?那将如何运作?谢谢。 是的,我很乐意解释 redux,但这应该是另一个问题的主题,我已经对您的代码进行了更多审查,您不应该在 componentWillMount 中进行任何异步调用,因为它可能会使您的表未初始化,因为状态变化可能未被检测到。你看过 React Table 控制组件的例子吗?它有一个你也可以玩的代码笔。 @donlaur 我已经检查了 codepen 上的代码。在这里您可以找到一个工作示例。享受。请不要忘记接受它作为答案。 codesandbox.io/s/wy574pkrl8 当我单击 A、B、C 按钮时尝试移动 codepen 示例时,我收到 TypeError 错误:props.filterFunc is not a function。【参考方案2】:

在 React 中,您可以在状态更改时更新组件。触发的唯一方法是使用 this.setState()

所以我会像这样改变我的状态对象:

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

所以这是新文件:

// In Directory.js
class 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>
);

在您致电alphaFilter() 后,您的组件将立即更新。当您将过滤器功能放入其中时,它会按预期显示。所以我会选择数组的.map()函数。您可以使用filter(),也可以在比较map()中的数据后返回

【讨论】:

我更改了代码,并且 word 确实显示按钮已被单击。如何在 DataGrid.js 文件的渲染中更新可过滤部分或 filterMethod,因为它仍然附加到输入字段并且不使用按钮?谢谢,有点迷路了,在这里很迷路。【参考方案3】:

对于 react-table 7,你可以监听外部的输入变化并调用setFilter

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

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

【讨论】:

以上是关于使用按钮在 React 中的 react-table 上触发过滤功能的主要内容,如果未能解决你的问题,请参考以下文章

react-table 在数据中渲染组件

如何从 JSON 文件加载 React-Table 中的图像

将多个数据添加到 react-table 中的列

如何在 React-Table 上获取单元格值?

反应表中的导出到 CSV 按钮

使用 React-Table 选择多行? (Shift + 单击)