【问题标题】:Best way to filter table in React在 React 中过滤表的最佳方法
【发布时间】:2016-02-23 16:33:28
【问题描述】:

我有一个存储在 redux 中的对象数组。我希望能够根据用户输入过滤该数组。我应该创建一个通过道具接收数组并修改该数组的状态对象,还是混合状态和道具是不好的做法?如果两者混用也可以,要不要在componentWillReceiveProps中设置状态?

【问题讨论】:

标签: javascript reactjs redux


【解决方案1】:

基于 props 构建状态可能有些复杂,这是可以接受的,但您应该考虑所有选项。

最简单的实现方法是在 render 方法中过滤道具。如果您有足够小的组件由于太多原因而没有更新,尤其是当列表中的元素数量很少时,这可能是首选方法:

class FilterList extends React.Component {
  render () {
    const { elements } = this.props;
    const { filterStr } = this.state;

    const filteredElements = elements
      .filter(e => e.includes(filterStr))
      .map(e => <li>{ e }</li>)

    return (
      <div>
        <input
          type="text"
          value={ filterStr }
          onChange={ e => this.setState({ filterStr: e.target.value }) } />
        <ul>
          { filteredElements }
        </ul>
      </div>
    );
  }
}

下一个选项是执行您所描述的操作,并根据组件的过滤器状态和传递给它的道具导出计算状态。当您有一个接收许多道具并经常渲染的复杂组件时,这很好。在这里,您缓存了可查看的元素,并且仅在需要过滤时才过滤列表。

class FilterList extends React.Component {
  constructor (props) {
    this.state = {
      viewableEls: props.elements
    }
  }

  componentWillReceiveProps (nextProps) {
    const { elements } = this.props;
    const { filterStr } = this.state;

    if (elements !== nextProps.elements) {
      this.setState({
        viewableEls: this.getViewableEls(nextProps.elements, filterStr)
      })
    }
  }

  getViewableEls (elements, filterStr) {
    return elements.filter(el => el.includes(filterStr))
  }

  handleFilterChange = e => {
    const { elements } = this.props;

    this.setState({
      filterStr: e.target.value,
      viewableEls: this.getViewableEls(elements, filterStr)
    })
  }
  render () {
    const { viewableEls } = this.state;

    return (
      <div>
        <input
          type="text"
          value={ filterStr }
          onChange={ this.handleFilterChange } />
        <ul>
          { viewableEls.map(e => <li key={ e }>{ e }</li>) }
        </ul>
      </div>
    );
  }
}

最后,redux 的“方式”,它要求您将动作创建者和filterStr 作为道具传递给组件,可能通过connect 传递到其他地方。下面的实现使用无状态组件,因为我们根本没有将fitlerStr 保持在组件状态。

const FilterTable = ({ elements, filterStr, changeFilterStr }) => {
  return (
    <div>
      <input
        type="text"
        value={ filterStr }
        onChange={ e => changeFilterStr(e.target.value) } />
      <ul>
        {
          elements
            .filter(e => e.includes(filterStr))
            .map(e => <li key={ e }>{ e }</li>)
        }
      </ul>
    </div>
  )
}

【讨论】:

  • 感谢您花时间深入回答问题!
  • 第一个和第三个例子都不错。然而,我必须对第二个例子提出异议。您的 this.state.viewableEls 完全来自 props 和 state,而 state 字段应该真正包含独特的信息。您声称这具有缓存优势,但我没有看到;因为只有在 props/state 更新时才会触发渲染。
  • 在人为的例子中,你是对的,'caching, but if you are receiving other props which trigger render, but which shouldn't affect the value of this.state.viewableEls, then there is. Unless I'm misunderstanding you, of course. Lets say 90% of the re-renders are triggered by the change of a prop which viewableEls` 不是 (让假设有一个实时聊天组件,它是一个子组件),而elements 在数以万计的元素范围内,每次有新消息通过时都会进行非平凡但不必要的重新计算。没有?
  • 为 redux 部分给了你一个 +1,而不是在商店中管理两个列表,只保留一个并保留过滤器/订单项
  • 在第二个例子中你是如何使用handleFilterChange函数的?
猜你喜欢
  • 1970-01-01
  • 2021-02-05
  • 2014-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 2018-03-11
相关资源
最近更新 更多