为什么在 React App 输入字段中键入 ANYTHING 会使我的 Persons 在基本的电话簿应用程序中显示为空白?

Why does typing ANYTHING in the React App input field make my Persons display blank for a rudimentary Phonebook App?

提问人:Worker1432 提问时间:11/10/2023 更新时间:11/10/2023 访问量:16

问:

我想做的是在我基本的 React 电话簿应用程序中创建一个搜索功能。人员的初始数据存储在项目根目录的 db.json 文件中。

这是一个有问题的代码,当我在输入字段中输入某些内容后,人员列表的整个显示都变为空白:

import React, {useState} from 'react';

const Search = ({persons, setPersons}) => {
    const [filter, setFilter] = useState('');

    const handleFilterEntry = (event) => {
        const value = event.target.value;
        setFilter(value);
        const filteredPersons = persons.filter( person => {
            person.name.toLowerCase().includes(value.toLowerCase())
        });
        setPersons(filteredPersons);
        console.log(value);
    }
    return (
        <div>
            Filter names with: <input value = {filter} onChange={handleFilterEntry}/>
        </div>
    )
}

export default Search;

这是修复该问题的handleFilterEntry函数的更新代码:

const handleFilterEntry = (event) => {
        const value = event.target.value;
        setFilter(value);

        const filteredPersons = value
            ? persons.filter(
                (person) =>
                    person.name.toLowerCase().includes(value.toLowerCase())
            )
            : persons;

        setPersons(filteredPersons);
        console.log(value);
    };

我想知道为什么添加条件逻辑有效并解决了问题?

我还想知道,在输入字段中向后退行某些字符时,为什么列表没有恢复为显示带有退格字母的人员列表。

示例:
列表中有 Joe 和 Jack 的名字。
我输入 J,它过滤到 Joe 和 Jack。
我输入 Jo,它过滤到 Joe。 但是我退格到只有 J,它不会恢复为在列表中同时显示 Joe 和 Jack,仍然只显示 Joe

任何帮助将不胜感激,我是新手。提前致谢!

javascript reactjs 数组 react-hooks 反应效果

评论


答:

1赞 ashish singh 11/10/2023 #1

第 1 部分。为什么它显示一个空列表

您没有在 filter 函数中返回检查值

person.name.toLowerCase().includes(value.toLowerCase())返回此值以使过滤器正常工作


第 2 部分。为什么退格不起作用?

  • 现在,最初您的列表是[jim, joe]

  • 在搜索它变成jo[joe]

  • 当您按退格键时,数组仍然是[joe]

  • 您已从该数组中删除,因此当您按退格键时,它不会出现在列表中jim

1赞 Nicholas Tower 11/10/2023 #2

我想知道为什么添加条件逻辑有效并解决了问题?

修复它的不是条件逻辑,而是你的过滤器函数现在返回一个值。你从这个开始:

persons.filter(person => {
  person.name.toLowerCase().includes(value.toLowerCase())
});

上面的函数有大括号标记出函数体,但它没有语句。然后,您切换到以下位置:return

persons.filter((person) =>
  person.name.toLowerCase().includes(value.toLowerCase())
)

大括号现在不见了。这意味着您使用的是箭头函数的简写版本。在速记语法中,javascript 会自动假定 .return

但是我退格到只有 J,它不会恢复为在列表中同时显示 Joe 和 Jack,并且仍然只显示 Joe。

那是因为您删除了该数据。每次键入字母时,都会收缩数组并设置状态。 永远不会增加数组的大小,所以当你删除一个字母时,它只会保持数组的大小与它已经相同的大小。.filter

解决方法是不改变;让它包含完整的数据集。然后,您将在渲染期间根据该列表计算过滤后的列表:persons

const Search = ({ persons, setPersons }) => {
  const [filter, setFilter] = useState("");
  const filteredPersons = persons.filter((person) =>
    person.name.toLowerCase().includes(filter.toLowerCase()),
  );

  const handleFilterEntry = (event) => {
    const value = event.target.value;
    setFilter(value);
  };
  return (
    <div>
      Filter names with: <input value={filter} onChange={handleFilterEntry} />
    </div>
  );
};

您可以使用 useMemo 提高其性能,以便仅在相关内容发生更改时重新计算:filteredPersons

const filteredPersons = useMemo(() => {
  return persons.filter((person) =>
    person.name.toLowerCase().includes(filter.toLowerCase()),
  );
}, [persons, filter]);