Why is the data for API calls undefined?
P粉726133917
P粉726133917 2024-01-29 13:46:53
0
1
453

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

P粉726133917
P粉726133917

reply all(1)
P粉716228245

Based on what I saw, The problem should be with this api call

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
}

})

should be

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
} catch (error) {
return error
}
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template