为什么用react-hooks过滤状态数组不起作用,但过滤原始数组可以

IT技术 javascript reactjs ecmascript-6
2021-04-28 06:57:07

基于来自用户的输入,我正在过滤一个数组。如果我使用teams来自状态的它不起作用,但如果我使用原始数组,它会正确过滤。谁能解释为什么会这样?我有点难住了。

这里有一个codeandbox供参考。

const teams_data = [
  "tottenham",
  "arsenal",
  "man utd",
  "liverpool",
  "chelsea",
  "west ham"
];

function App() {
  const [teams, setTeams] = React.useState(teams_data);
  const [search, setSearch] = React.useState("");

  return (
    <div className="App">
      <input
        onChange={e => {
          // if I filter on teams below it doesn't work as it should
          // but if I use teams_data (original array) it works
          const filteredTeams = teams_data.filter(team => {
             return team.toLowerCase().includes(e.target.value.toLowerCase());
          });
          setTeams(filteredTeams);
          setSearch(e.target.value);
        }}
        type="text"
        value={search}
      />
      {teams.map(team => (
        <p>{team}</p>
      ))}
    </div>
  );
}
4个回答

如果过滤teams然后setTeams,则只能从集合中删除团队。当开始时您的过滤器不匹配任何内容时,它已经将您减少teams到一个空数组。teams_data另一方面,如果您使用,则您始终可以将所有团队用于过滤器。

这是因为您将过滤后的结果保存为新状态。这意味着您只过滤掉结果,但永远不会将它们添加回来。

您在 codeandbox 上的实现是正确的实现,而过滤teams则不是。但是,您可能会做的是仅在搜索框值的长度变小时过滤整个数组。这样,在使用大数据集或查询服务器以获取结果时,过滤将变得更加轻量级。

这条线

setTeams(filteredTeams);

在第一次输入时破坏整个数组。

相反,您应该创建另一个数组:

const [filteredTeams, setFilteredTeams] = React.useState(teams_data);
...
          const tempFilteredTeams = teams_data.filter(team => {
             return team.toLowerCase().includes(e.target.value.toLowerCase());
          });
          setFilteredTeams(tempFilteredTeams);
const [persons, setPersons] = useState([
 { name: "qwerty", id: 1, number: 12345 },
 { name: "abc", id: 2, number: 1234567 },
 { name: "def", id: 3, number: 12345890 }   
]);

有对象数组时如何过滤输入字段中输入的名称?