0

Inside a reducer I'm using the filter method to delete a movie from a localStorage on user click. All the movies are deleted from the localStorage except the last one that will be delete from my state, but not from the localStorage. It seems the problem comes from the fact that my component isn't re-rendered when the last item is deleted from the state so my useEffect won't be triggered. The bug occurs only when I'm on the /watched route, I can delete all the items from LS if I'm on "/".

MoviesContext.js:

    const initialState = {
        movies: [],
        favoriteMovies: JSON.parse(localStorage.getItem('favorite')) || [],
        watchedMovies: JSON.parse(localStorage.getItem('watched')) || [],
    }

MoviesReducer.js

        case 'DELETE_MOVIE_FROM_WATCHED':
            return {
                ...state,
                watchedMovies: state.watchedMovies.filter(
                    item => item.id !== action.payload
                ),
            }

useMovies.js:

    const { favoriteMovies, watchedMovies, dispatch } = useContext(MoviesContext)

    const deleteMovieFromLS = async (id) => {
        dispatch({ type: 'DELETE_MOVIE_FROM_WATCHED', payload: id })
    }

    useEffect(() => {
        localStorage.setItem('watched', JSON.stringify(watchedMovies))
    }, [watchedMovies])
ekno
  • 69
  • 6

1 Answers1

1

It doesn't update state because the object reference is the same. You are setting watchedMovies to watchedMovies

if you spread the [...state.watchedMovies]

or JSON.parse(JSON.stringify(state.watchedMovies)) it should work

Try

MoviesContext.js:

    const initialState = {
        movies: [],
        favoriteMovies: JSON.parse(localStorage.getItem('favorite')) || [],
        watchedMovies: JSON.parse(localStorage.getItem('watched')) || [],
    }

MoviesReducer.js

        case 'DELETE_MOVIE_FROM_WATCHED':
            return {
                ...state,
                watchedMovies: [...state.watchedMovies].filter(
                    item => item.id !== action.payload
                ),
            }

useMovies.js:

    const { favoriteMovies, watchedMovies, dispatch } = useContext(MoviesContext)

    const deleteMovieFromLS = async (id) => {
        dispatch({ type: 'DELETE_MOVIE_FROM_WATCHED', payload: id })
    }

    useEffect(() => {
        localStorage.setItem('watched', JSON.stringify(watchedMovies))
    }, [watchedMovies])
  • It doesn't work, thanks anyway. What I find weird is that the bug occurs only when deleting the last item and when I'm on the route /watched. If I try to delete my movies from the home page they will all be deleted from the LS. – ekno Jun 10 '22 at 13:02