Фильтр поиска по имени и фамилии в React ведет себя не так, как ожидалось

#reactjs #search #filter #react-hooks

Вопрос:

Я создаю простой динамический поисковый фильтр, который отфильтровывает данные, но не точно по имени и фамилии. Мне нужно, чтобы это было точно по имени и фамилии. Например, если я наберу «кому» и имя, например «том», или фамилию, например «толлисон».

Вот компонент:

 import React, { useState, useEffect } from "react"
import SearchBar from "./components/SearchBar"
import axios from "axios"
import "./App.css"

function App() {
  const [students, setStudents] = useState(null)
  const [searchTerm, setSearchTerm] = useState("")
 
 useEffect(() => {
   const fetchStudents = async () => {
     const result = await axios("https://api.hatchways.io/assessment/students")
     setStudents(result.data.students)
   }
   fetchStudents()
 }, [])



  const convertStudentGrades = (grades) =>
    grades.map((grade) => parseInt(grade))

  const getStudentAverage = (grades) =>
    grades.reduce((sum, elem) => sum   elem, 0) / grades.length

  const capitalizeFullName = (first, last) => (
    <span>{`${first.toUpperCase()} ${last.toUpperCase()}`}</span>
  )


  return (
    <div className='container'>
      <input type="text" value={searchTerm} onChange={e => setSearchTerm(e.target.value)} placeholder="Search..." />
    
     
        {students amp;amp; students.filter(student => {
         if (searchTerm == "") {
            return student  
         } else if (student.firstName[0].includes(searchTerm.toLowerCase()) || student.lastName.includes(searchTerm.toLowerCase())) {
           return student
         }
        }).map(student => (
          <div className='row' key={student.id}>
            <div className='student-image'>
              <img src={student.pic} alt='' />
            </div>

            <div className='student-info'>
              <h1>
                <span>
                  {capitalizeFullName(student.firstName, student.lastName)}
                </span>
              </h1>
              <p>Email: {student.email}</p>
              <p>Company: {student.company}</p>
              <p>Skill: {student.skill}</p>
              <p>
                Average:{" "}
                {getStudentAverage(convertStudentGrades(student.grades))}
              </p>
            </div>
          </div>
        ))}
    </div>
  )
}

export default App
 

Я также хотел бы переместить этот уродливый метод фильтрации в JSX в метод, чтобы немного его очистить.

Ответ №1:

Вам нужно использовать startsWith вместо contains .

 const filteredStudent = () => {
    return students amp;amp; searchTerm !== "" ? students.filter(student => student.firstName[0].startsWith(searchTerm.toLowerCase()) || student.lastName.startsWith(searchTerm.toLowerCase())) : students;
}

  return (
    <div className='container'>
      <input type="text" value={searchTerm} onChange={e => setSearchTerm(e.target.value)} placeholder="Search..." />
    
     
        {filteredStudent().map(student => (
          <div className='row' key={student.id}>
            <div className='student-image'>