i have another "movie database" application in react. At the mount it renders movies based on api key which is set to "new movies". Then i have useEffect which update movie list based on searchbar and its value. Problem is, it renders new movies and just after that renders movies based on searchbar value which is empty. I know that useEffect is running on mount. What is best practice to use it this way? Or is there any better hook for this particular use? Thank you.
React.useEffect(() => {
fetch(
`https://api.themoviedb.org/3/search/movie?api_keylanguage=en-US&query=${searchValue}&`
)
.then((res) => res.json())
.then((data) => {
setMovies(data.results);
});
}, [searchValue]);
CodePudding user response:
Hey @JSpadawan best practice is to use filter like-
const [data,setData] = useState()
useEffect(()=>{
const apiData = fetch(APILINK).then((res)=>res.json()).catch(err)
if(apiData.length>0){
setData(apiData)
}
},[])
This will set the data of api.. now use filter like-
const [searchValue, setSearchValue]= useState()
const filterData = data && data.filter((data)=>data.includes(searchValue))
After this you can use filterdata any where you want. If you still facing issue just lemme know, i will help you more. Thanks
CodePudding user response:
You can set the movies with the useEffect, but I would recommend having a secondary useEffect that would be for the seach bar. You should try to avoid making tons of API calls as the more you make, the more it will slow down the application. So have one useEffect that will set the data, and a second one that you can filter out the ones that match the search bar.
If the searchValue is updated every key stroke then searching for a movie with a long title would create tons of API calls. You could put the fetch call in an async/await function so you get the data, then set it, then you can filter with a different effect.
useEffect(() => {
const getData = async () => {
await fetch(
`https://api.themoviedb.org/3/search/movie?api_keylanguage=en-US&query=${searchValue}&`
)
.then((res) => res.json())
.then((data) => {
setMovies(data.results);
});
}
getData();
}, []); // empty array will run once on component load, or add a dependency of when you want it to re-call the api
Then a second useEffect for filtering
useEffect(() => {
let searchTextFilter = movies.filter(i => {
return (!searchValue || (searchValue && i.Title.toLowerCase().includes(searchFilter?.toLowerCase() )))
});
}, [searchValue])