Reputation: 87
Using The Movie Database API, my app searches movies by title and also generates movies by selected genres. Even when I successfully search for titles and genres I get an error 422 "query must be provided." When I refresh the page random movies render for a second and then disappear waiting for my query. I am thinking there may be something wrong with my dependencies [query,genre]
in my useEffect
. I am new to React so in fear of not posting a section that may be the culprit I will post my full App.js file. Here is the code:
function App() {
const [search, setSearch] = useState("");
const [query, setQuery] = useState("");
const [movies, setMovies] = useState([]);
const [genre, setGenre] = useState("");
const API_KEY = "APIKEY";
useEffect(() => {
async function fetchMovies() {
const response = await fetch(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&page=2&include_adult=false&query=${query}`
);
const data = await response.json();
const moviesWithOnlyPosters =
data.results &&
data.results.filter(item => (item.poster_path != null ? item : null));
setMovies(moviesWithOnlyPosters);
}
async function fetchGenres() {
const response = await fetch(
`https://api.themoviedb.org/3/discover/movie?api_key=${API_KEY}&sort_by=popularity.desc&include_adult=false&include_video=false&page=2&with_genres=${genre}`
);
const data = await response.json();
console.log(data);
const moviesWithOnlyPosters =
data.results &&
data.results.filter(item => (item.poster_path != null ? item : null));
setMovies(moviesWithOnlyPosters);
}
fetchMovies();
fetchGenres();
}, [query, genre]);
function updateSearch(e) {
setSearch(e.target.value);
}
function getQuery(e) {
e.preventDefault();
setQuery(search);
setSearch("");
}
function handleGenreChange(e) {
setGenre(e.target.value);
}
return (
<div className="App">
<h1 className="app-title">What 2 Watch</h1>
<form onSubmit={getQuery}>
<Container fluid={true}>
<Row>
<Col xs="12" sm="6" className="search-bar-col">
<input
className="search-bar"
type="text"
placeholder="Search Title..."
value={search}
onChange={updateSearch}
/>
<button className="search-button" type="submit">
Search
</button>
</Col>
<Col xs="12" sm="6" className="genre-dropdown-col">
<select
className="genre-dropdown"
onChange={handleGenreChange}
value={genre}
>
<option hidden>Find by Genre</option>
<option value="28">Action</option>
<option value="12">Adventure</option>
<option value="16">Animation</option>
<option value="35">Comedy</option>
<option value="99">Documentary</option>
<option value="14">Fantasy</option>
<option value="36">History</option>
<option value="27">Horror</option>
<option value="9648">Mystery</option>
<option value="10749">Romance</option>
<option value="878">Science Fiction</option>
<option value="53">Thriller</option>
<option value="10752">War</option>
<option value="37">Western</option>
</select>
</Col>
</Row>
</Container>
</form>
<Row>
{movies &&
movies.map(item => (
<Col xs="12" md="6" lg="4" key={item.id}>
<Movie
key={item.id}
title={item.title}
year={item.release_date}
image={item.poster_path}
description={item.overview}
/>
</Col>
))}
</Row>
</div>
);
}
export default App;
Upvotes: 0
Views: 1198
Reputation: 6837
The reason for the error is the component App
is rendered with the default state value of query
on the first render. Because the state value of query
is initialized as an empty string(""
), the first time the App
component renders there is no query to search for so the fetch call inside fetchMovies
is called with a URL value of,
"https://api.themoviedb.org/3/search/movie?api_key=your-api-key&page=2&include_adult=false&query="
Which results to 422 unknown
because no query was provided in the URL .
Solution
Make the fetch call to the API only if the is query value exists. The same logic can be applied if the fetchGenres
call if it also fails with 422 unknown
error.
I also suggest that you provide the query value as an argument to the function fetchMovies
and include a try...catch
block in the function to better handle the error cases when the API call fails.
async function fetchMovies(queryValue) {
if (!queryValue) {
return
}
try {
const response = await fetch(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&page=2&include_adult=false&query=${query}`
);
// rest of your state related logic
} catch(error) {
// handle the error
}
}
Keep in mind when invoking the function pass the state variable query
as argument to the function fetchMovies
fetchMovies(query)
Upvotes: 1