filtering array based on each letter from input

醉酒当歌 提交于 2021-02-10 20:16:11

问题


I am filtering an array of students based on input from the textbox. How can I get this to work to show students as you type out the first name? My solution is working, but obviously, if you were to backspace, the student array does not re populate. How can I get this to filter as you type the name of the student and also repopulate the array when you backspace?

function App() {
  const [student, setStudent] = useState([]);

  useEffect(() => {
    fetch(api)
      .then((response) => response.json())
      .then((result) => {
        setStudent(result.students);
        
      })
      .catch((err) => {
        console.error(err);
      });
  }, [setStudent]);

  const filter = (e) => {
    for (let i = 0; i < student.length; i++) {
      const searchedStudent = student.filter((name) => {
        return name.firstName.toLowerCase().includes(e.target.value);
      });

      setStudent(searchedStudent);
    }
  };

  return (
    <>
      <input
        placeholder="Search by name"
        type="text"
        className="filter-students"
        onChange={filter}
      />
      {student.map((students) => {
        let total = 0;
        for (let i = 0; i < students.grades.length; i++) {
          total += parseInt(students.grades[i]);
        }

        const average = total / students.grades.length;
        console.log(average);

        return (
          <ul className="student-container">
            <img className="student-img" src={students.pic} />

            <div className="student-column">
              <li className="student-item">
                {" "}
                {students.firstName} {students.lastName}
              </li>
              <li className="student-item">Email: {students.email}</li>
              <li className="student-item">Company: {students.company}</li>
              <li className="student-item">Skill: {students.skill}</li>

              <li className="student-item">Average: {average}%</li>
            </div>
          </ul>
        );
      })}
    </>
  );
}

回答1:


The problem is student state gets updated every time the <input> changes.

Note that filtering results into a derived data coming from the original data.

Thus, NO NEED to store the filtered/derived results as a state.

Rather, you need to have another state for the text used for filtering.

const [student, setStudent] = useState([]);
const [filter, setFilter] = useState(""); // state for the text filter

<input
  placeholder="Search by name"
  type="text"
  className="filter-students"
  onChange={(e) => setFilter(e.target.value)}
/>

{students
  .filter((name) => name.firstName.toLowerCase().includes(filter)) // use filter state
  .map(/* Add elements here */)
}




回答2:


Don't filter your state and save it back over itself, this doesn't allow you to get back to your original state. Instead, use a separate piece of state to save the filter value and filter in-line when rendering state so you can keep your student data intact and unmutated by filtering.

function App() {
  const [student, setStudent] = useState([]);
  const [filterValue, setfilterValue] = useState(""); // <-- filter state

  return (
    <>
      <input
        placeholder="Search by name"
        type="text"
        className="filter-students"
        onChange={(e) => setFilterValue(e.target.value)} // <-- update filter state
      />
      {student
        .filter((name) => { // <-- filter inline
          return name.firstName.toLowerCase().includes(e.target.value);
        })
        .map((students) => {
          let total = 0;
          for (let i = 0; i < students.grades.length; i++) {
            total += parseInt(students.grades[i]);
          }

          const average = total / students.grades.length;
          console.log(average);

          return (
            <ul className="student-container">
              <img className="student-img" src={students.pic} />

              <div className="student-column">
                <li className="student-item">
                  {" "}
                  {students.firstName} {students.lastName}
                </li>
                <li className="student-item">Email: {students.email}</li>
                <li className="student-item">Company: {students.company}</li>
                <li className="student-item">Skill: {students.skill}</li>

                <li className="student-item">Average: {average}%</li>
              </div>
            </ul>
          );
        })}
    </>
  );
}


来源:https://stackoverflow.com/questions/64674657/filtering-array-based-on-each-letter-from-input

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!