I can load my data but only after I refresh the page. Until then, it shows the data from the previous item I clicked on. It's behaving like a cache would.
Here is my mediaSlice
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 HBO_SINGLE_MEDIA_API = `${BASE_URL}/titlestest`
const initialState = {
media:{},
status: 'idle', //'idle', 'loading', 'succeeded', 'failed'
error:null
}
export const fetchSingleMediaTitle = createAsyncThunk(
'media/fetchSingleMediaTitle',
async (id) => {
const response = await axios.get(
HBO_SINGLE_MEDIA_API,
{
headers: {
'Content-Type': 'application/json',
'X-API-KEY': KEY,
},
params: {
titleId: id,
}
}
)
return response.data.Item;
}
)
const mediaSlice = createSlice({
name: 'media',
initialState,
reducers:{},
extraReducers: {
[fetchSingleMediaTitle.pending]: () => {
console.log("Pending");
},
[fetchSingleMediaTitle.fulfilled]: (state, { payload }) => {
state.status = 'succeeded'
state.media = payload
},
[fetchSingleMediaTitle.rejected]: () => {
console.log("Rejected");
},
}
})
// SELECTORS
export const selectSingleMedia = (state) => state.media.media;
export const getMediaStatus = (state) => state.media.status;
export default mediaSlice.reducer
And then the Media Component has what you would expect
const [media, setMedia] = useState([]);
const {id} = useParams();
const dispatch = useDispatch();
const singlemedia = useSelector((state) => selectSingleMedia(state, id))
const mediaStatus = useSelector(getMediaStatus)
useEffect(() => {
if (mediaStatus === 'idle') {
dispatch(fetchSingleMediaTitle(id)) //yes, it's imported
}
setMedia(singlemedia);
//it returns the array with the data but not the current one
console.log("singlemedia: ", singlemedia);
return () => { };
// Someone suggested removing the dependencies below but then it doesn't load anything.
}, [id, singlemedia, mediaStatus, dispatch, media_data])
I am at a loss here because as I understand it, the useEffect is supposed to fire onload and give me the current data. The ID is correct in the params but the state is not mutating.
Thanks in advance
EDIT For reference, here is the console log. Those console logs are in the useEffect. The API is slightly slower than the useEffect and the render is happening before the data is ready (race condition) or at least that's what I think it's happening here that's why it loads empty and then it loads again. But the confusing part is that ALL of that happens on a page refresh only. On a normal load the state is not empty is loaded and in time for the UI to render it (no race condition), only, it's loaded with the old data from a previous state shape
Your selector takes one argument, but you're passing it two. Change it to:
const singlemedia = useSelector(selectSingleMedia);
Second, your singlemedia
is the state. There's no need to setMedia(singlemedia);
.
Your useEffect
should look like:
useEffect(() => {
if (mediaStatus === 'idle') {
dispatch(fetchSingleMediaTitle(id));
}
}, [dispatch, id, mediaStatus]);
Also, you should look into RTK Query, which would replace createAsyncThunk
: https://redux-toolkit.js.org/tutorials/rtk-query
useEffect(() => {
dispatch(fetchSingleMediaTitle(id));
}, [dispatch, id]);