Лучший способ фильтрации таблицы в 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>
)
}