У меня есть массив объектов, хранящихся в редуксе. Я хочу, чтобы иметь возможность фильтровать этот массив на основе ввода пользователем. Должен ли я создать объект состояния, который получает массив через реквизит и модифицирует этот массив, или это плохая практика для смешивания состояния и реквизита? Если это нормально, смешайте два, должен ли я установить состояние в компонентеWillReceiveProps?
Лучший способ фильтрации таблицы в реакторе
Ответ 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={ this.handleFilterChange } />
<ul>
{ viewableEls.map(e => <li key={ e }>{ e }</li>) }
</ul>
</div>
);
}
}
И, наконец, "путь" для filterStr
, который требует, чтобы вы передавали создатель действия и 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>
)
}