I can't figure it out why it's returning undefined, when i'm using the useSelector
In console log it showing Uncaught TypeError: movies.results is undefined
error logmovieLising.js(without render movies) console.log
store.js
import {configureStore} from '@reduxjs/toolkit';
import moviesReducer from './movies/movieSlice';
export const store = configureStore({
reducer:{
movies:moviesReducer
}
})
movieSlice.js
Here is the slice where i defined the initial state reducer and actions
import {createSlice,createAsyncThunk} from '@reduxjs/toolkit';
import movieApi from '../../common/api/movieApi';
const API_KEY = process.env.REACT_APP_API_KEY;
export const fetchAsyncMovies = createAsyncThunk(
"movies/fetchAsyncMovies",
async () => {
const movieTerm ="harry";
const response = await
movieApi.get(`/search/movie?api_key=${API_KEY}&query=${movieTerm}`);
// console.log(response.data);
return response.data;
}
);
const initialState = {
movies:{},
}
const movieSlice = createSlice({
name:"movies",
initialState,
reducers:{
addMovies:(state,{payload}) =>{
state.movies= payload;
}
},
extraReducers:{
[fetchAsyncMovies.pending]: () => {
console.log("Pending");
},
[fetchAsyncMovies.fulfilled]: (state, { payload }) => {
console.log("Fetched Successfully!");
return { ...state, movies: payload };
},
[fetchAsyncMovies.rejected]: () => {
console.log("Rejected!");
},
}
});
export const {addMovies} = movieSlice.actions;
export const getAllMovies = (state) => state.movies.movies;
export default movieSlice.reducer
Home.js
This is the Home component where i use the useDispatch
import React, { useEffect } from 'react';
import MovieListing from '../MovieListing/MovieListing';
import {useDispatch} from "react-redux";
import {fetchAsyncMovies} from "../../features/movies/movieSlice"
const Home = () => {
const dispatch = useDispatch();
useEffect(()=>{
dispatch(fetchAsyncMovies());
},[dispatch]);
return(
<div>
<div className="banner-img"></div>
<MovieListing/>
</div>
) ;
};
export default Home;
MovieListing.js(COMPONENT)
import React from 'react';
import {useSelector} from 'react-redux';
import {getAllMovies} from '../../features/movies/movieSlice';
import MovieCard from '../MovieCard/MovieCard';
import './movieListing.scss'
const MovieListing = () => {
const movies = useSelector(getAllMovies);
let renderMovies ="";
renderMovies = movies.results.length > 0 ? (movies.results.map((movie,index)=>(
<MovieCard key={index} data={movie} />
))) :(
<div className="movies-error">
<h3>{movies.Error}</h3>
</div>
);
console.log(movies.results);
return (
<div className="movie-wrapper">
<div className="movie-list">
<h2>Movies</h2>
<div className="movie-container">
{renderMovies }
</div>
</div>
</div>
);
};
export default MovieListing;
Since you defined your initial state as :
const initialState = { movies:{}, }
In the very first render, movies.results
is undefined
, so trying to use the length
property leads to an error.
try defining your initial state like this:
const initialState = { movies:{results:[]}, }
another solution would be always checking if movies.results
is defined, before using its properties:
renderMovies = movies.results && movies.results.length > 0 ? ...