Skip to main content

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.
fetchPodcasts
AsyncThunk
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:
src/App.js
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:
.addCase(fetchPodcasts.pending, (state) => {
  state.loading = true;
})
Sets loading to true when the fetch begins.

Actions

toggleFavorite

Toggles a podcast episode in the user’s favorites list.
action.payload
object
required
title
string
required
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.
action.payload
object
required
title
string
required
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.
action.payload
string
required
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.
action.payload
string
required
The title of the podcast episode to remove
dispatch(removeFromCompleted("Episode Title"));

setSearchTerm

Updates the search query for filtering episodes.
action.payload
string
required
The search term to filter episodes
dispatch(setSearchTerm("nadie sabe"));
Usage Example:
src/App.js
const handleSearchChange = (e) => {
  dispatch(setFilter("todos"));
  dispatch(setSearchTerm(e.target.value));
};

Bulk Clear Actions

Actions for clearing entire collections:
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:
nsnPodcastFavorites
string[]
Array of favorite episode titles
nsnPodcastCompleted
string[]
Array of completed episode titles
nsnPodcastListenLater
string[]
Array of “listen later” episode titles
nsnPodcastListened
string[]
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';

Build docs developers (and LLMs) love