I'm doing this in other components very similarly, except this one takes a parameter of title_id. I am getting my data to fetch when I check the Redux DevTool and I console logged the payload from the mediaSlice too, but the useSelector in my Component is bringing nothing in and not updating my state. Can you help me figure out what exactly is it that I am messing up on so my selector can send the payload to my Component's state?
I made comments/questions in my code below where I think my problem areas are.
Here is my mediaSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";
const KEY = process.env.REACT_APP_API_KEY
const BASE_URL = process.env.REACT_APP_BASE_URL
const SINGLE_MEDIA_API = `${BASE_URL}/titlestest`
const initialState = {
media:[],
status: 'idle',
error:null
}
export const fetchSingleMediaTitle = createAsyncThunk(
'medias/fetchSingleMediaTitle',
async (mediaId) => { // <-- would this be where I declare the param key I am using?
try {
const response = await axios.get(
SINGLE_MEDIA_API,
{
headers: {
'Content-Type': 'application/json',
'X-API-KEY': KEY,
},
params: {
titleId: mediaId,
}
}
)
return response.data.Item;
} catch (error) {
console.error('API call error:', error.message);
}
}
)
const mediaSlice = createSlice({
name: 'medias',
initialState,
reducers:{},
extraReducers(builder) {
builder
.addCase(fetchSingleMediaTitle.pending, (state, action) => {
state.status = 'loading'
})
.addCase(fetchSingleMediaTitle.fulfilled, (state, action) => {
state.status = 'succeeded'
const loadedMedia = action.payload
state.media = loadedMedia
console.log("loadedMedia: ", loadedMedia); // this is successfully printing the data object
})
.addCase(fetchSingleMediaTitle.rejected, (state, action) => {
state.status = 'failed'
state.error = action.error.message
})
}
})
// SELECTORS
export const selectSingleMedia = (state, mediaId) => state.media.media.find(item => item.title_id === mediaId); //this is where I am suspecting the problem is in
export const getMediaStatus = (state) => state.media.status;
export const getMediaError = (state) => state.media.error;
export default mediaSlice.reducer
And my Component. Reduced for brevity
import React, { useState, useEffect, useRef, Fragment } from 'react'
import { useSelector, useDispatch } from 'react-redux';
import { getMediaError, getMediaStatus, selectSingleMedia, fetchSingleMediaTitle } from '../../features/medias/mediaSlice'
import { useParams, useHistory } from "react-router-dom";
const SingleMediaTitle = () => {
//STATES
const [data, setData] = useState([]);
const {mediaId} = useParams();
const dispatch = useDispatch();
const media = useSelector((state, mediaId) => selectSingleMedia(state, mediaId)) //This is a suspect line too
const mediaStatus = useSelector(getMediaStatus)
const error = useSelector(getMediaError)
useEffect(() => {
if (mediaStatus === 'idle') {
dispatch(fetchSingleMediaTitle(mediaId))
}
setData(media);
console.log("media: ", media); // This is undefined
}, [mediaId, media, mediaStatus, dispatch])
let content;
if (mediaStatus === 'loading') {
content = <Box className="loading">
<Typography variant="subtitle2">Loading ..</Typography>
</Box>
} else if (mediaStatus === 'succeeded') {
content = <Box>
{media.content_source} //Though redux succeeded, this is not displaying
<Box/>
} else if (mediaStatus === 'failed') {
content = <Box className="loading">
<Typography variant="subtitle2">{error}</Typography>
</Box>
}
return (
<Box sx={{p:3, pt:9}}> {content} </Box>
)
}
export default SingleMediaTitle
I really appreciate your help. Being the only front end dev in house is tough lol