#reactjs #search #filter #components #state
Вопрос:
Я работаю над приложением reactjs. Я использую общедоступный API для получения данных учащихся, а затем отображаю их в основном компоненте, т. е. App.js. Мне также нужно выполнить поиск-отфильтровать студентов по их именам. Затем я должен добавить функциональность компонента тегов, которая позволяет мне добавлять теги любому студенту в приложении. например, «tag1, tag2, собака и т. Д.» Любому студенту. До сих пор все в порядке.
Сейчас у меня возникли проблемы с созданием поискового фильтра для тегов. Мне нужен «Поиск по тегу» прямо под «Поиск по имени» в «App.js» компонент и я создали компонент тегов в другой папке «Tags.js».
App.js
import "./App.css"; import { Collapsible } from "./Collapsible"; import Card from "react-bootstrap/Card"; import { Tags } from "./Tags"; import { ListGroupItem } from "react-bootstrap"; class App extends React.Component { // Constructor constructor(props) { super(props); this.state = { items: [], isLoaded: false, filter: "", min: 1, max: 9, }; } // ComponentDidMount is used to // execute the code componentDidMount() { fetch("#") .then((res) =gt; res.json()) .then((res) =gt; { this.setState({ items: res.students, isLoaded: true, }); }); } handleChange = (event) =gt; { this.setState({ filter: event.target.value }); }; render() { const { isLoaded, items, filter } = this.state; const lowercasedFilter = filter.toString().toLowerCase(); const filteredData = items.filter((item) =gt; { return Object.keys(item).some((key) =gt; item[key].toString().toLowerCase().includes(lowercasedFilter) ); }); if (!isLoaded) return ( lt;divgt; lt;h1gt; Please wait some time.... lt;/h1gt;{" "} lt;/divgt; ); return ( lt;div className="App"gt; lt;Card className="students" style={{ width: "50rem" }}gt; lt;input className="searchBar" type="text" value={filter} onChange={this.handleChange} placeholder="Search by name" /gt; {filteredData.map((item) =gt; ( lt;ListGroupItem className="studentList"gt; lt;ol className="ol" key={item.id}gt; lt;Card.Img className="img" src={item.pic} /gt; lt;Card.Text className="data text-dark"gt; lt;div className="upperBox"gt; lt;Card.Title className="title"gt; {item.firstName} {item.lastName} lt;/Card.Titlegt; Email: {item.email} lt;brgt;lt;/brgt; Company: {item.company} lt;brgt;lt;/brgt; Skills: {item.skill} lt;brgt;lt;/brgt; Average:{" "} {item.grades.reduce((a, b) =gt; a parseInt(b), 0) / item.grades.length}{" "} % lt;/divgt; lt;Collapsiblegt; lt;div className="grades"gt; {item.grades.map((grade, i) =gt; { if (i gt;= this.state.min amp;amp; i lt;= this.state.max) { return ( lt;ul className="gradesList"gt; lt;divgt;Test {i}:lt;/divgt; lt;divgt;{grade} %lt;/divgt; lt;/ulgt; ); } })} lt;/divgt; lt;/Collapsiblegt; lt;Tags /gt; lt;/Card.Textgt; lt;/olgt; lt;/ListGroupItemgt; ))} lt;/Cardgt; lt;/divgt; ); } } export default App;
Tags.js
export class Tags extends React.Component { constructor(props) { super(props); this.state = { tags: [], }; } removeTag = (i) =gt; { const newTags = [...this.state.tags]; newTags.splice(i, 1); this.setState({ tags: newTags }); }; inputKeyDown = (e) =gt; { const val = e.target.value; if (e.key === "Enter" amp;amp; val) { if ( this.state.tags.find((tag) =gt; tag.toLowerCase() === val.toLowerCase()) ) { return; } this.setState({ tags: [...this.state.tags, val] }); this.tagInput.value = null; } else if (e.key === "Backspace" amp;amp; !val) { this.removeTag(this.state.tags.length - 1); } }; render() { const { tags } = this.state; return ( lt;div className="input-tag"gt; lt;ul className="input-tag__tags"gt; {tags.map((tag, i) =gt; ( lt;li key={tag}gt; {tag} lt;button type="button" onClick={() =gt; { this.removeTag(i); }} gt; lt;/buttongt; lt;/ligt; ))} lt;li className="input-tag__tags__input"gt; lt;input className="input" placeholder="Add a tag" type="text" onKeyDown={this.inputKeyDown} ref={(c) =gt; { this.tagInput = c; }} /gt; lt;/ligt; lt;/ulgt; lt;/divgt; ); } }