I have run into a weird bug with my search input component where it loses focus on every keypress and can't figure out why.
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>
  );
};
I'm also getting a Line 65:50:  Expected to return a value at the end of arrow function  array-callback-return for the characters.filter() line so I don't know if that has to do with it.
If it helps, the deployed app with the bug can be seen here --> https://mundane-vacation.surge.sh
To fix input losing focus when rerendering with React, we should define child components outside the parent component. const Child = () => <p>Child! </p>; const Parent = () => <Child />; to define the Child component outside the Parent .
To set focus on an input field after rendering with React, we can assign a ref to the input element with the useRef hook. Then we call focus on the current value of the ref to focus on the input. to call useRef to create a ref and assign it to inputReference . Then we call inputReference.
input s provided to Fields as their component props are created anew after every keystroke. This causes them to lose focus, despite having an unique, constant key.
You have a problem with focus because your component SearchBar is declared inside App component and it is recreated on each rendering. You need to move SearchBar out of App or just move StyledInput on the place of SearchBar. If you choose the first way, I recommend you remove React.Fragment from SearchBar, because it has only one rendered child:
function SearchBar(props) {
    return (
        <StyledInput
          type="text"
          id="search"
          value={props.value}
          placeholder="Search by name..."
          onChange={props.onChange}
        />
    );
  }
And in App:
<SearchBar onChange={handleSearch} value={search} />
To fix your warning, you need always return a boolean value inside the filter function. Now you return nothing (i.e. undefined) in case if the character does not pass the condition. So change your filter function like this:
const filtered = characters.filter(character => {
    return character.name.toLocaleLowerCase().indexOf(e.target.value) !== -1
});
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With