最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - why filtering state array with react hooks doesn't work but filtering original array does - Stack Overflow

programmeradmin0浏览0评论

Based on an input from a user I am filtering over an array. It doesn't work if I use the teams from the state, but if I use the original array it does filter correctly. Can anyone explain why this is happening? I am a bit stumped.

There is a codesandbox here for reference.

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>
  );
}

Based on an input from a user I am filtering over an array. It doesn't work if I use the teams from the state, but if I use the original array it does filter correctly. Can anyone explain why this is happening? I am a bit stumped.

There is a codesandbox here for reference.

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>
  );
}
Share Improve this question edited Sep 2, 2019 at 9:36 peter flanagan asked Sep 2, 2019 at 9:31 peter flanaganpeter flanagan 9,84027 gold badges81 silver badges140 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 7

If you filter teams and then setTeams, you can only remove teams from the collection. When at the beginning your filter does not match anything, it already reduces your teams to an empty array. If you use teams_data on the other hand you always have all your teams available to the filter.

This is because you save the filtered result as the new state. This means you only filter out results, but never add them back in.

The implementation that you have on codesandbox is a correct implementation, whereas filtering on teams is not. However what you potentially could do is filter the full array only when the length of your search box value bees smaller. That way, filtering would bee more light weight, when using big datasets or when querying the server for the results.

This line

setTeams(filteredTeams);

destroys your entire array at the first input.

Instead, you should make another array:

const [filteredTeams, setFilteredTeams] = React.useState(teams_data);
...
          const tempFilteredTeams = teams_data.filter(team => {
             return team.toLowerCase().includes(e.target.value.toLowerCase());
          });
          setFilteredTeams(tempFilteredTeams);

Just check if input has value

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 (e.target.value) {
            const filteredTeams = teams.filter(team => {
              return team.toLowerCase().includes(e.target.value.toLowerCase());
            });
            setTeams(filteredTeams);
          } else {
            setTeams(teams_data);
          }
          setSearch(e.target.value);

        }}
        type="text"
        value={search}
      />
      {teams.map(team => (
        <p>{team}</p>
      ))}
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论