I'm writing a website. It's a website that uses and fetches data from a stock API to displays stock prices and charts.
I have a search bar which changes state whenever a letter is typed in.. However, it's causing problems because it's instantly updating the state, which then fetches data from the API, and if for example I type in Z - then the API is instalty looking for a stock named "Z" and the app crashes, goes blank ( because such link doesnt exist ). I literally have to copy the stock name like "AAPL" for example and then paste it - for the app to work properly.
var baseUrl = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${search}&apikey=**********`;
because state of "search" is updated and it's searching for that stock/
Anyways, here's my stock search bar component.
const StockSearchBar = () => {
const { search, setSearch } = useContext(SearchContext); // i'm using context API to store state so I can access it across different components
const handleClick = (e) => {
if (setSearch !== '') { // if there's something in state, then post data to backend
const options =
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({search}),
};
const response = fetch(`http://localhost:3001/api/search`, options);
};
function handleButtonEvents(e) { // i'm using a function to chain handleClick() and setTimeout() to be run when button is clicked
e.preventDefault();
handleClick();
setTimeout(() => window.location.reload(), 3000); // delay the function for 3 seconds to give it time to fetch the data and display it, otherwise it might refresh the page without updating it with new data
}
const handleSearch = e => {
e.preventDefault();
setSearch(e.target.value.toUpperCase()); // i think the problem is here - i need to delay setting state
}
return (
<>
<div className="searchBar">
<label>Look for Stocks or Cryptos: </label>
<input type='text' onChange={handleSearch} onKeyPress={(ev) => {
if (ev.key === "Enter") { handleButtonEvents(); }}}
{/* search if Enter key is pressed */} // i think the problem is with **onChange** or the handleSearch **function** but not sure how to deal with it
placeholder={search} required />
<Button variant="success" type="submit" onClick={handleButtonEvents} >Search</Button>
</div>
<h1 className="src">{search}</h1>
{// display state to see if it's changing ( just testing }
</>
);
};
export default StockSearchBar;
Let me know if you want to see the context API file, or something else. But I think the probem is in the search bar component.
Thank you in advance for help.
CodePudding user response:
you need to use Debounce
in order to create a delay e.g. from lodash. so in your case it would be
const handleSearch = e => {
e.preventDefault();
debounce(setSearch(e.target.value.toUpperCase()), 500)// debounce 500 milliseconds
}