I built a movie web application using React.js. The data works fine when I call it on the API. However, when I try to switch pages via API call id
, the data becomes undefined. I use the Redux toolkit to call the data.
But when I try to press the card, one of the pages I set up to get the data from the selected card happens like the picture below
I tried checking the console log and the results are as follows.
If you want to check the code
.env
sorry i can share api key VITE_BASE_URL=https://api.themoviedb.org/3 VITE_IMG_PATH=https://image.tmdb.org/t/p/w500 VITE_VIDEO_PATH=https://api.themoviedb.org/3/movie
api.js
import Axios from 'axios' export const movieList = Axios.create({ baseURL: `${import.meta.env.VITE_BASE_URL}` })
action.js
import { createAsyncThunk } from "@reduxjs/toolkit"; import { movieList } from "../../service/api/api"; export const fetchMovieAll = createAsyncThunk('movie/fetchMovieAll', async() => { try { const api = `api_key=${import.meta.env.VITE_TMDB_KEY}` const respone = await movieList.get(`discover/movie?${api}`) return respone.data.results } catch (error) { return error } }) export const fetchMovie = createAsyncThunk('movie/fetchMovie', async(id) => { try { const respone = await movieList.get(`/movie/${id}?api_key=${import.meta.env.VITE_TMDB_KEY}`) return respone.data.results } catch (error) { return error } })
slice.js
import {createSlice} from '@reduxjs/toolkit' import * as movieAction from '../action' const movieDb = createSlice({ name: 'movieDb', initialState: { loading: false, data: [], entity: { id: null, title: '', release_date: '', popularity: '', poster_path: '', overview: '', vote_average: '', backdrop_path: '' }, error: null, }, extraReducers: (builder) => builder.addCase(movieAction.fetchMovieAll.pending, (state) => { state.loading = true }) .addCase(movieAction.fetchMovieAll.fulfilled, (state, action) => { state.loading = false, state.data = action.payload }) .addCase(movieAction.fetchMovieAll.rejected, (state) => { state.loading = true, state.error = action.payload }) .addCase(movieAction.fetchMovie.pending, (state) => { state.loading = true }) .addCase(movieAction.fetchMovie.fulfilled, (state, action) => { state.loading = false, state.entity = action.payload }) .addCase(movieAction.fetchMovie.rejected, (state) => { state.loading = true, state.error = action.payload }) }) export default movieDb.reducer;
store.js
import { configureStore } from "@reduxjs/toolkit"; import movieDbReducer from '../slice' export default configureStore({ reducer: { movieDb: movieDbReducer, } })
CardMovie.jsx
import React, { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { fetchMovieAll } from '../../../manage/action' import style from './style.module.css' import { useNavigate } from 'react-router-dom' function CardMovie() { const dispatch = useDispatch() const {data} = useSelector((state) => state.movieDb) const navigate = useNavigate() const fetchDataMovie = async() => { dispatch(fetchMovieAll()) } const goToDetail = (id) => { navigate(`/detail/${id}`) } useEffect(() => { fetchDataMovie() console.log(data) },[]) return ( <> {data.map((item) => { return ( <div key={item.id} className={style['main-card']} onClick={() => goToDetail(item.id)}> <div className={style['card-content']}> <img src={`${import.meta.env.VITE_IMG_PATH}${item.poster_path}`} alt="poster" /> <div className={style['card-title']}> <p>{item.title}</p> </div> </div> </div> ) })} </> ) } export default CardMovie
Details.jsx
import React, { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { useNavigate, useParams } from 'react-router-dom' import { fetchMovie } from '../../manage/action' function Detail() { const {id} = useParams() const dispatch = useDispatch() // const navigate = useNavigate() const {entity} = useSelector((state) => state.movieDb) const fetchDataMovie = async(movieId) => { dispatch(fetchMovie(movieId)) } useEffect(() => { fetchDataMovie(id) console.log(entity) },[]) return ( <> <div> <h1>Detail</h1> {/* <h5>{entity.title}</h5> */} </div> </> ) } export default Detail
App.jsx
import Home from "./page/Home" import Genre from "./page/Genre" import Detail from "./page/Detail" import './App.css' import {Outlet, RouterProvider, createBrowserRouter} from 'react-router-dom' function App() { const router = createBrowserRouter([ { path: '/', children: [ { index: true, element: <Home/> }, { path: 'genre', element: <Genre/> }, { path: 'detail/:id', element: <Detail/> } ] } ]) return ( <> <RouterProvider router={router}/> <Outlet/> </> ) } export default App
index.jsx
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.jsx' import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/js/bootstrap.js' import { Provider } from 'react-redux' import store from './manage/store/index.js' ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, )
I'm trying to do what this website refers to.
If I click on some cards, the result will be like this
But what I get is this and this
Based on what I saw, The problem should be with this api call
})
should be