On successful api calls it runs fine but when I try to handle an empty search it gives me an error, I have checked the code it should render the error message. When clicking the search btn i get the error. It should render text saying query must be provided. I thought it might be the render logic in my search component but i dont see the problem. I also checked the state and the reducer but no luck
// search component that renders movies, error message, and loading message
import React, {
Fragment,
useState,
useContext
} from 'react';
import MovieContext from '../../context/movie/movieContext';
import ErrorStyle from '../styles/ErrorStyle';
import PropTypes from 'prop-types';
import MoviesStyle from '../styles/MoviesStyle';
import MovieItem from '../movie/MovieItem';
import InputStyle from '../styles/InputStyle';
import SearchStyle from '../styles/SearchStyle';
import FormStyle from '../styles/FormStyle';
function Search() {
const movieContext = useContext(MovieContext);
const {
Search,
movies,
errorMessage,
loading
} = movieContext;
console.log(errorMessage);
const [search, setSearch] = useState('');
const handleChange = e => {
setSearch(e.target.value);
};
const clearSearch = () => {
setSearch('');
};
const searchFunction = e => {
e.preventDefault();
Search(search);
clearSearch();
};
return (<Fragment>
<FormStyle action=''>
<SearchStyle type='text' value={search} onChange={handleChange} placeholder='Search'/>
<InputStyle onClick={searchFunction} type='submit' value='SEARCH'/>
</FormStyle>
< p className='App-intro'>
Search for your favourite movies
</p>
< MoviesStyle >
{loading && !errorMessage
? (< span > loading... < /span>): errorMessage ? ( <ErrorStyle> {errorMessage} </ErrorStyle>)
: (movies.map((movie, index) => (< MovieItem key = { `${index}:${movie.Title}`} movie = {movie} />)))
}
< /MoviesStyle></Fragment>);
}
Search.protoTypes = {
search: PropTypes.string.isRequired
};
export default Search;
// state using context api, holds search function to make requests
import React, {
useReducer
} from 'react';
import MovieContext from './movieContext';
import MovieReducer from './MovieReducer';
const MovieState = props => {
const initialState = {
loading: false,
movies: [],
errorMessage: null
};
// using our reducer and initial state in useReducer
const [state, dispatch] = useReducer(MovieReducer, initialState);
// makes request to the api
const Search = searchValue => {
dispatch({
type: 'SEARCH_MOVIE_REQUEST'
});
fetch(`https://api.themoviedb.org/3/search/movie?query=${searchValue}&api_key=d107fa42623e9a747b66f9da4ec90364`).then(response => response.json()).then(jsonResponse => {
console.log(jsonResponse);
if (jsonResponse) {
dispatch({
type: 'SEARCH_MOVIE_SUCCESS',
payload: jsonResponse.results
});
} else {
dispatch({
type: 'SEARCH_MOVIE_FAILURE',
errors: jsonResponse.errors[0]
});
}
});
};
return ( < MovieContext.Provider value = {
{
loading: state.loading,
movies: state.movies,
errorMessage: state.errorMessage,
Search
}
} > {
props.children
} < /MovieContext.Provider>);
};
export default MovieState;
// reducer
export default (state, action) => {
switch (action.type) {
case 'SEARCH_MOVIE_REQUEST':
return {
...state,
loading: true,
errorMessage: null
};
case 'SEARCH_MOVIE_SUCCESS':
return {
...state,
loading: false,
movies: action.payload
};
case 'SEARCH_MOVIE_FAILURE':
return {
...state,
loading: false,
errorMessage: action.errors
};
default:
return state;
}
};
Your payload
is probably empty as you didn't get any results.
Try replacing this line of code:
movies: action.payload
By this, to add an undefined
check:
movies: action.payload || []
Haha wow im such a newb, thank you! The result of staring code way to long.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.