У меня есть список элементов li, который передается одному из моих компонентов. Они отображаются в компоненте. У меня есть панель поиска в том же компоненте. Я хочу иметь возможность отображать только те элементы, которые соответствуют тому, что написано в строке поиска. Вот так выглядит мой компонент.
import React, {Component} from 'react'
import {NavLink} from 'react-router-dom'
import LikeBtn from './LikeBtn'
class SearchForm extends Component {
constructor(props) {
super(props)
this.state = {
search: '',
newList: []
}
}
handleChangeEvent = (e) => {
this.setState({
[e.target.name]: e.target.value,
})
}
render() {
let list = this.props.listProp.map(item => <li className = "listItem" key = {item.id}><NavLink style = {{ color: 'white' }} to = {`activities/${item.id}`}>{item.name}</NavLink><LikeBtn /></li>)
let newList = list.filter(item => item.innerText === this.state.search)
console.info(newList)
return (
<>
<input type = "text" name='search' onChange = {this.handleChangeEvent}/>
<ul>
{list}
</ul>
</>
)
}
}
export default SearchForm
Я не знаю, как отфильтровать это, чтобы я мог отображать элементы. Я пытался сделать innerText, но поскольку у меня есть компонент LikeBtn в элементе li, мой фильтр не работает. Как еще я мог бы реализовать это? Есть ли более эффективные способы сделать это?
Вам нужно фильтровать свои данные и не захватывать то, что вы уже отобразили на экране.
render() {
let filteredList = this.state.search
? this.props.listProp.filter((item) =>
item.name.includes(this.state.search),
)
: this.props.listProp;
return (
<>
<input type = "text" name = "search" onChange = {this.handleChangeEvent} />
<ul>
{filteredList.map((item) => (
<li className = "listItem" key = {item.id}>
<NavLink style = {{ color: 'white' }} to = {`activities/${item.id}`}>
{item.name}
</NavLink>
<LikeBtn />
</li>
))}
</ul>
</>
);
}
Ниже также есть фрагмент, который вы можете запустить:
class SearchForm extends React.Component {
constructor(props) {
super(props);
this.state = {
search: '',
};
}
handleChangeEvent = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
render() {
let filteredList = this.state.search
? this.props.listProp.filter((item) =>
item.name.toLowerCase().includes(this.state.search.toLowerCase())
)
: this.props.listProp;
return (
<React.Fragment>
<input type = "search" name = "search" autocomplete = "off" onChange = {this.handleChangeEvent} />
<ul>
{filteredList.map((item) => (
<li className = "listItem" key = {item.id}>
<a href = {`activities/${item.id}`}>{item.name}</a>
<button>Like</button>
</li>
))}
</ul>
</React.Fragment>
);
}
}
const data = [
{
id: 1,
name: 'Congress, The',
},
{
id: 2,
name: 'Glen or Glenda',
},
{
id: 3,
name: "Don't Drink the Water",
},
{
id: 4,
name: 'Blind',
},
{
id: 5,
name: 'Sirocco',
},
{
id: 6,
name: 'Sunset Strip',
},
{
id: 7,
name: 'Better Living',
},
{
id: 8,
name: '4:44 Last Day on Earth',
},
{
id: 9,
name: 'The Heavy',
},
{
id: 10,
name: 'Dr. Who and the Daleks',
},
{
id: 11,
name: 'Legend of Hell House, The',
},
{
id: 12,
name: 'Exit Humanity',
},
{
id: 13,
name: 'Young in Heart, The',
},
{
id: 14,
name: 'Soul Kitchen',
},
{
id: 15,
name: 'Accattone',
},
];
ReactDOM.render(<SearchForm listProp = {data} />, document.querySelector('#root'));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id = "root"></div>
Вы можете переместить эту часть
let list = this.props.listProp.map(item => <li className = "listItem" key = {item.id}><NavLink style = {{ color: 'white' }} to = {`activities/${item.id}`}>{item.name}</NavLink><LikeBtn /></li>)
для возврата и фильтрации listProp на handleChangeEvent.
Вы можете обратиться к этому коду Sandbox здесь для рабочего образца