Overview
The podcast slice is the core state manager for episode data, handling:
Fetching episodes from the API
Managing user collections (favorites, completed, listen later)
Search functionality
Episode metadata and loading states
State Shape
{
songs : [], // Array of podcast episodes
loading : true , // API loading state
error : null , // Error message if fetch fails
listenedEpisodes : [], // Episodes user has started
favoriteEpisodes : [], // User's favorite episodes
completedEpisodes : [], // Episodes marked as completed
listenLaterEpisodes : [], // Episodes saved for later
searchTerm : "" // Current search query
}
Async Thunks
fetchPodcasts
Fetches all podcast episodes from the API.
Fetches podcast episodes from the remote API endpoint
src/store/slices/podcastSlice.js
export const fetchPodcasts = createAsyncThunk (
"podcast/fetchPodcasts" ,
async () => {
const response = await axios . get (
"https://nsn-podcast-api-rapidapi.netlify.app/podcast"
);
return response . data . allEpisodes ;
}
);
Usage Example:
import { useEffect } from 'react' ;
import { useDispatch } from 'react-redux' ;
import { fetchPodcasts } from './store/slices/podcastSlice' ;
const App = () => {
const dispatch = useDispatch ();
useEffect (() => {
dispatch ( fetchPodcasts ());
}, [ dispatch ]);
// ...
};
States:
Pending
Fulfilled
Rejected
. addCase ( fetchPodcasts . pending , ( state ) => {
state . loading = true ;
})
Sets loading to true when the fetch begins. . addCase ( fetchPodcasts . fulfilled , ( state , action ) => {
state . loading = false ;
state . songs = action . payload ;
state . error = null ;
})
Updates songs array with fetched data and clears loading/error states. . addCase ( fetchPodcasts . rejected , ( state , action ) => {
state . loading = false ;
state . error = action . error . message ;
})
Sets error message when the fetch fails.
Actions
toggleFavorite
Toggles a podcast episode in the user’s favorites list.
The title of the podcast episode
dispatch ( toggleFavorite ({ title: "Episode Title" }));
Reducer Logic:
src/store/slices/podcastSlice.js
toggleFavorite : ( state , action ) => {
const songTitle = action . payload . title ;
const isFavorite = state . favoriteEpisodes . includes ( songTitle );
if ( isFavorite ) {
state . favoriteEpisodes = state . favoriteEpisodes . filter (
( title ) => title !== songTitle
);
} else {
state . favoriteEpisodes . push ( songTitle );
}
localStorage . setItem (
"nsnPodcastFavorites" ,
JSON . stringify ( state . favoriteEpisodes )
);
}
Real Usage:
src/components/PodcastDetail/PodcastDetail.jsx
const handleFavorites = () => {
dispatch ( toggleFavorite ( podcast ));
};
toggleListenLater
Toggles a podcast episode in the “listen later” list.
The title of the podcast episode
dispatch ( toggleListenLater ({ title: "Episode Title" }));
Example:
src/components/PodcastDetail/PodcastDetail.jsx
const handleWatchLater = () => {
if ( isListenLater ) {
dispatch ( toggleListenLater ( podcast ));
} else {
dispatch ( toggleListenLater ( podcast ));
}
};
markAsCompleted
Marks a podcast episode as completed.
The title of the podcast episode to mark as completed
dispatch ( markAsCompleted ( "Episode Title" ));
Reducer Logic:
src/store/slices/podcastSlice.js
markAsCompleted : ( state , action ) => {
const songTitle = action . payload ;
if ( ! state . completedEpisodes . includes ( songTitle )) {
state . completedEpisodes . push ( songTitle );
localStorage . setItem (
"nsnPodcastCompleted" ,
JSON . stringify ( state . completedEpisodes )
);
}
}
Usage in PersistentPlayer:
src/components/PersistentPlayer/PersistentPlayer.jsx
const handleEnded = () => {
dispatch ( updatePlaybackTime ({ title: currentPodcast . title , time: 0 }));
dispatch ( markAsCompleted ( currentPodcast . title ));
};
removeFromCompleted
Removes a podcast episode from the completed list.
The title of the podcast episode to remove
dispatch ( removeFromCompleted ( "Episode Title" ));
setSearchTerm
Updates the search query for filtering episodes.
The search term to filter episodes
dispatch ( setSearchTerm ( "nadie sabe" ));
Usage Example:
const handleSearchChange = ( e ) => {
dispatch ( setFilter ( "todos" ));
dispatch ( setSearchTerm ( e . target . value ));
};
Bulk Clear Actions
Actions for clearing entire collections:
clearFavorites
clearListenLater
clearStarted
clearCompleted
dispatch ( clearFavorites ());
// Clears all favorite episodes
Settings Page Example:
src/components/Settings/Settings.jsx
const handleClearAll = () => {
showConfirmToast (
"¿Estás seguro de que quieres borrar TODOS los datos?" ,
() => {
dispatch ( clearStarted ());
dispatch ( clearFavorites ());
dispatch ( clearListenLater ());
dispatch ( clearCompleted ());
dispatch ( clearPlaybackTimes ());
showSuccessToast ( "Todos los datos han sido eliminados" );
}
);
};
Selectors
Access podcast state in components using useSelector:
import { useSelector } from 'react-redux' ;
const MyComponent = () => {
const {
songs ,
loading ,
error ,
favoriteEpisodes ,
completedEpisodes ,
listenLaterEpisodes ,
searchTerm
} = useSelector (( state ) => state . podcast );
// Use the state...
};
Real Example:
src/components/PodcastDetail/PodcastDetail.jsx
const {
songs ,
listenedEpisodes ,
completedEpisodes ,
favoriteEpisodes ,
listenLaterEpisodes
} = useSelector (( state ) => state . podcast );
const isCompleted = completedEpisodes . includes ( podcast . title );
const isFavorite = favoriteEpisodes . includes ( podcast . title );
const isListenLater = listenLaterEpisodes . includes ( podcast . title );
LocalStorage Keys
The podcast slice persists data to localStorage:
Array of favorite episode titles
Array of completed episode titles
Array of “listen later” episode titles
Array of started episode titles
Complete Action Reference
import {
fetchPodcasts , // Async thunk to fetch episodes
toggleFavorite , // Toggle favorite status
toggleListenLater , // Toggle listen later status
markAsCompleted , // Mark episode as completed
removeFromCompleted , // Remove from completed list
setSearchTerm , // Update search query
deleteEpisode , // Delete episode (placeholder)
clearFavorites , // Clear all favorites
clearListenLater , // Clear listen later list
clearStarted , // Clear started episodes
clearCompleted // Clear completed episodes
} from './store/slices/podcastSlice' ;