I'm using next js for my application, and I am designing a search field. The suggestions start coming in once the user types something, but I would like to hide it when the input bar is not in focus.
When the user clicks on it again, I would like to show it back. The search suggestions contain routes, so I am not able use onFocus and onBlur as the element loses focus when I register a click and the route happens only when I release it.
I tried css too, but I'm not able to register the focus out, or is there a way?
Please help me out!!
Here is my sample code:
const [suggestionState,setSuggestionState] = useState(false);
<input type="input"
ref={inputRef}
autoFocus
className={styles['search-bar-input']}
onFocus={()=>{setSuggestionState(true)}}
onBlur={()=>{setSuggestionState(false)}}
placeholder="Search Bloggo"
onChange={(e)=>{
var trimmedQuery = e.target.value;
trimmedQuery = trimmedQuery.trim();
setSearchQuery(trimmedQuery);
getSuggestions(trimmedQuery)
}}
onKeyDown={(e)=>{handleKeypress(e)}}
/>
{
searchQuery.length == 0 || suggestionState == false? '':
<div className={styles['search-bar-suggestions']}>
<Link>... </Link>
</div>
}
You could do this with css :focus-within
.suggestions {
display: none;
}
form:focus-within .suggestions {
display: block;
}
input:focus~.suggestions {
display: block;
}
<form>
<input type="input" placeholder="Search Bloggo" value="">
<div class="suggestions">Suggestions...
<div><a href="#">Suggestion 1</a></div>
<div><a href="#">Suggestion 2</a></div>
<div><a href="#">Suggestion 3</a></div>
<div><a href="#">Suggestion 4</a></div>
</div>
</form>
Applying the above in react might looks something like this:
import "./styles.css";
import { useState, useEffect } from "react";
export default function App() {
const [searchQuery, setSearchQuery] = useState("");
const [results, setResults] = useState([]);
useEffect(() => {
if (!searchQuery) {
setResults([]);
return;
}
fetch(`https://rickandmortyapi.com/api/character/?name=${searchQuery}`)
.then((response) => response.json())
.then(({ results }) => setResults(results));
}, [searchQuery]);
return (
<form>
<input
value={searchQuery}
type="input"
autoFocus
placeholder="Search Bloggo"
onChange={(e) => {
setSearchQuery(e.target.value);
}}
/>
{!!results.length && (
<div className={`suggestions `}>
<h3>Suggestions</h3>
{results.map((result) => {
return (
<Link key={result.id} url={result.url}>
{result.name}
</Link>
);
})}
</div>
)}
</form>
);
}
const Link = ({ url, children }) => (
<div>
<a href={url}>{children}</a>
</div>
);