Javascript 在 React 中过滤表格的最佳方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35582978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:55:34  来源:igfitidea点击:

Best way to filter table in React

javascriptreactjsredux

提问by Juliuszc

I have an array of objects stored in redux. I want to be able to filter that array based on user input. Should I create a state object that receives the array through props and modify that array, or is it bad practice to mix state and props? If it is alright to mix the two, should I set the state in componentWillReceiveProps?

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

回答by Nathan Hagen

Building state based on props can be somewhat complicated, which is acceptable, but you should consider all of your options.

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

The simplest to implement is to filter the props in your rendermethod. If you have sufficiently small components which don't update for too many reasons, and especially if the number of elements in the list is low, this might be the preferred method:

最简单的实现是过滤你的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>
    );
  }
}

The next option is to do what you're describing, and derive a computed state based of the component's filter state and props passed to it. This is good when you have a complicated component which recieves many props and is rendered often. Here, you're caching the viewable elements and only filtering the list when it needs to be filtered.

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

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

And finally, the redux 'way', which requires you to pass the action creator and filterStras props to the component, probably passed in via connectsomewhere else. The implementation below is using a stateless component since we're not keeping the fitlerStrin the component state at all.

最后,redux 'way',它要求您将动作创建者和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>
  )
}