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