React - 输入框在按键时失去焦点

8
我在搜索输入组件中遇到了一个奇怪的bug,每次按键都会失去焦点,但我不知道原因。
const App = () => {
  let [characters, setCharacters] = useState([]);
  let [filteredCharacters, setFilteredCharacters] = useState([]);
  // more state
  let [search, setSearch] = useState("");

  useEffect(() => {
    setIsLoading(true);
    axios
      .get(`https://swapi.co/api/people/?page=${pageNumber}`)
      .then(res => {
        console.log(res.data.results);
        setCharacters(res.data.results);
        setFilteredCharacters(res.data.results);
      })
      .catch(err => console.error(err))
      .then(() => {
        setIsLoading(false);
      });
  }, [pageNumber]);

  function updatePage(e) {
     // update page
  }

  function handleSearch(e) {
    setSearch(e.target.value);
    const filtered = characters.filter(character => {
      if (character.name.toLocaleLowerCase().indexOf(e.target.value) !== -1) {
        return character;
      }
    });
    setFilteredCharacters(filtered);
  }
  function SearchBar() {
    return (
      <React.Fragment>
        <StyledInput
          type="text"
          id="search"
          value={search}
          placeholder="Search by name..."
          onChange={e => handleSearch(e)}
        />
      </React.Fragment>
    );
  }

  return (
    <React.Fragment>
      <GlobalStyles />
      <div className="App">
        <Heading>React Wars!</Heading>
        <SearchBar />
        <Pagination handleClick={updatePage} />
        {!isLoading && Object.entries(filteredCharacters).length ? (
          <CharacterList characters={filteredCharacters} />
        ) : (
          <LoadingBar />
        )}
      </div>
    </React.Fragment>
  );
};

我还遇到一个问题:Line 65:50: Expected to return a value at the end of arrow function array-callback-return,这可能与characters.filter()有关。

如果有帮助的话,可以在这里查看存在错误的应用程序-->https://mundane-vacation.surge.sh


4
在React中,如果在输入字符时输入框失去焦点,99%的情况是因为它正在重新渲染。我猜测这是因为您已经将函数组件嵌套在另一个组件内并将其用作子元素。SearchBaronChange调用handleSearch,后者调用setSearch,从而更改状态值,从而导致重新渲染(包括SearchBar子元素本身的重新渲染)。查看其他类似问题的解决方法,请参考以下链接:https://dev59.com/R1gQ5IYBdhLWcg3wkEtJ - Jayce444
你每次渲染时都在定义 function SearchBar() { ,所以它是一个全新的组件,每次都会被重新评估和渲染。你可以省略它,并将 StyledInput 内容注入到 <SearchBar /> 的位置,这样应该会有所帮助。 - Derek
你收到的警告/错误是因为你的“characters”过滤函数器应该每次返回一个布尔值,而不是当前函数器的值。你可以简单地返回该名称的tolowercase索引检查的值。 - Derek
这对我很有帮助!因为它更加明显:https://dev59.com/R1gQ5IYBdhLWcg3wkEtJ#59287017 - Sandip Mane
1个回答

8
由于你的组件 SearchBar 声明在 App 组件内,每次渲染都会重新创建导致你存在聚焦问题。 你需要将 SearchBar 移出 App 或者只是将 StyledInput 移到 SearchBar 的位置。如果你选择第一种方式,建议你从 SearchBar 中删除 React.Fragment,因为它只有一个渲染的子元素。
function SearchBar(props) {
    return (
        <StyledInput
          type="text"
          id="search"
          value={props.value}
          placeholder="Search by name..."
          onChange={props.onChange}
        />
    );
  }

应用中:

<SearchBar onChange={handleSearch} value={search} />

为了解决你的警告,你需要在 `filter` 函数内始终返回一个布尔值。现在如果 `character` 不符合条件,你返回了空值(即 `undefined`)。因此,请按照以下方式更改你的 `filter` 函数:
const filtered = characters.filter(character => {
    return character.name.toLocaleLowerCase().indexOf(e.target.value) !== -1
});

你的回答帮助我解决了我的问题。谢谢。 - codrelphi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接