Лучший способ фильтрации таблицы в React

У меня есть массив объектов, хранящихся в клетку. Я хочу иметь возможность фильтровать массива на основе пользовательского ввода. Должен ли я создать объект состояния, который получает массив через props и изменяет этот массив, или это плохая практика смешивать state и props? Если это нормально, чтобы смешать два, Должен ли я установить состояние в componentWillReceiveProps?

1 ответов


состояние здания на основе реквизита может быть несколько сложным, что приемлемо, но вы должны рассмотреть все свои варианты.

самый простой в реализации-фильтровать реквизит в вашем 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={ e => this.setState({ filterStr: e.target.value }) } />
        <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>
  )
}