My project is a youtube clone site and I'm trying to return video data from Back-End using Node.js, Axios and Redux-Toolkit But the response value is always null and when I don't use dispatch, I can return the data from the backend and I don't know why. I tried a lot, but I can't find a solution I need your help thanks
Store.js
import { configureStore, combineReducers } from '@reduxjs/toolkit'
import userReducer from '../redux/userSlice.js'
import videoReducer from '../redux/videoSlice.js'
import storage from 'redux-persist/lib/storage'
import { PersistGate } from 'redux-persist/integration/react'
import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER, } from 'redux-persist'
const persistConfig = {
key: 'root',
version: 1,
storage,
}
const rootReducer = combineReducers({ user: userReducer, video: videoReducer })
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
})
export const persistor = persistStore(store)
videoSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
currentVideo: null,
loading: false,
error: false,
};
export const videoSlice = createSlice({
name: "video",
initialState,
reducers: {
fetchStart: (state) => {
state.loading = true;
},
fetchSuccess: (state, action) => {
state.loading = false;
state.currentVideo = action.payload;
},
fetchFailure: (state) => {
state.loading = false;
state.error = true;
},
},
})
export const { fetchStart, fetchSuccess, fetchFailure } = videoSlice.actions
export default videoSlice.reducer
Video.jsx
import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
import ThumbUpAltOutlinedIcon from '@mui/icons-material/ThumbUpAltOutlined';
import ThumbDownAltOutlinedIcon from '@mui/icons-material/ThumbDownAltOutlined';
import ReplayOutlinedIcon from '@mui/icons-material/ReplayOutlined';
import AddTaskOutlinedIcon from '@mui/icons-material/AddTaskOutlined';
import Comments from '../components/Comments'
import Card from '../components/Card'
import { useDispatch, useSelector } from "react-redux";
import { useLocation } from "react-router-dom";
import axios from 'axios';
import { fetchStart, fetchSuccess, fetchFailure } from '../redux/videoSlice'
import { format } from 'timeago.js';
const Container = styled.div`
display: flex;
gap: 1.5rem;
`
const Content = styled.div`
flex: 5;
`
const Recommendation = styled.div`
flex: 2;
`
const VideoWrapper = styled.div`
`
const Details = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`
const Info = styled.span`
color: ${({ theme }) => theme.textSoft};
`
const Hr = styled.hr`
border: 0.5px solid ${({ theme }) => theme.soft};
`
const Title = styled.h1`
font-size: 18px;
font-weight: 400;
margin-top: 20px;
margin-bottom: 10px;
color: ${({ theme }) => theme.text};
`
const Buttons = styled.div`
display:flex;
gap: 20px;
color: ${({ theme }) => theme.text};
`
const Button = styled.div`
display: flex;
align-items: center;
gap:5px;
cursor: pointer;
`
const Chanel = styled.div`
display:flex;
justify-content:space-between;
`
const ChanelInfo = styled.div`
display:flex;
gap: 20px;
`
const Image = styled.img`
width: 50px;
height:50px;
border-radius: 50%;
`
const ChanelDetails = styled.div`
display:flex;
flex-direction:column;
color: ${({ theme }) => theme.text};
`
const ChanelName = styled.span`
font-weight: 500;`
const ChanelCounter = styled.span`
margin-top: 5px;
margin-bottom:20px;
color: ${({ theme }) => theme.textSoft};
font-size:12px ;
`
const Description = styled.p`
font-size:12px ;
`
const Subscripe = styled.button`
background-color: red;
font-weight: 500;
color: white;
border: none;
border-radius: 3px;
height: max-content;
cursor: pointer;
padding: 10px 20px;
`
const Video = () => {
const { currentVideo } = useSelector((state) => state.video);
const dispatch = useDispatch();
console.log('currentVideo',currentVideo);
const path = useLocation().pathname.split("/")[2];
const [channel, setChannel] = useState({});
// const [video, setVideo] = useState({});
useEffect(()=> {
const fetchData = async () => {
try {
dispatch(fetchStart())
const videoRes = await axios.get(`/videos/find/${path}`);
const channelRes = await axios.get(`/users/find/${videoRes.data.userId}`);
setChannel(channelRes.data);
dispatch(fetchSuccess(videoRes.data))
} catch (err) {
dispatch(fetchFailure())
}
};
fetchData();
}, [path, dispatch]);
return (
<Container>
<Content>
<VideoWrapper>
<iframe width="100%" height="720" src="https://www.youtube.com/embed/vkc99WHcDTk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</VideoWrapper>
<Title>{currentVideo.title}</Title>
<Details>
<Info>{currentVideo.views} views {format(currentVideo.createdAt)} </Info>
<Buttons>
<Button>
<ThumbUpAltOutlinedIcon /> {currentVideo.likes?.length}
</Button>
<Button>
<ThumbDownAltOutlinedIcon /> Dislike
</Button>
<Button>
<ReplayOutlinedIcon /> Share
</Button>
<Button>
<AddTaskOutlinedIcon /> Save
</Button>
</Buttons>
</Details>
<Hr />
<Chanel>
<ChanelInfo>
<Image src={channel.img} />
<ChanelDetails>
<ChanelName>{channel.name}</ChanelName>
<ChanelCounter>{channel.subscribers} subscriper</ChanelCounter>
<Description>{currentVideo.description}</Description>
</ChanelDetails>
</ChanelInfo>
<Subscripe>Subscripe</Subscripe>
</Chanel>
<Hr />
<Comments />
</Content>
{/* <Recommendation>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
<Card type="sm"/>
</Recommendation> */}
</Container>
)
}
export default Video