Home > Enterprise >  I am displaying list of songs with an option to delete specific songs if the current user has upload
I am displaying list of songs with an option to delete specific songs if the current user has upload

Time:12-08

This is the component

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { deleteSong, getSongs } from '../../store/song';

import ReactAudioPlayer from 'react-audio-player';


const SongList = () => {
    const dispatch = useDispatch();

    const songsObj = useSelector((state) => state.songState.entries);
    const songs = Object.values(songsObj)

    const user = useSelector((state) => state.session.user);
    const CurrentUserId = user?.id

    const userSongs = songs.filter(song => song.userId === CurrentUserId)

    const remove = async () => {
        const songId = 10
        dispatch(deleteSong(songId));
    }

    useEffect(() => {
        dispatch(getSongs());
    }, [dispatch]);


    return (
        <div>
            <h1>Song List</h1>
            <ol>
                {songs.map(({ id, songName, songLink, userId }) => (
                    <div className='songdetails' key={id}>
                        <p key={id}>songName={songName}</p>
                        {userId === CurrentUserId ?
                            <div>
                                <button id={id} onClick={remove}>remove</button>
                            </div>
                            : null}
                    </div>
                ))}
            </ol>
        </div>
    );
};
export default SongList;

These are the routes

router.get('/', asyncHandler(async (req, res) => {
const songs = await Song.findAll();
res.json(songs);
}));

router.post('/:id', requireAuth, songValidations.validateCreate, asyncHandler(async (req, res) => {
    const song = await Song.create(req.body);
    return res.json(song);
}));

router.delete('/:id', requireAuth, asyncHandler(async function (req, res) {
    const song = await Song.findByPk(req.params.id)
    if (!song) throw new Error('Cannot find song');
    await Song.destroy({ where: { id: song.id } });

    return song.id


}));

And the store

import { csrfFetch } from "./csrf";
const LOAD_SONGS = 'song/loadSongs';
const ADD_SONG = 'song/addSongs';
const REMOVE_SONG = 'song/removeSongs'

export const loadSongs = (songs) => ({
    type: LOAD_SONGS,
    songs
});
export const getSongs = () => async (dispatch) => {
    const response = await fetch('/api/songs')
    const songs = await response.json()
    dispatch(loadSongs(songs))
    return songs
}

export const addSong = (newSong) => ({
    type: ADD_SONG,
    newSong
});

export const postSong = (newSong) => async (dispatch) => {
    const response = await csrfFetch(`/api/songs/${newSong.id}`, {
        method: 'post',
        body: JSON.stringify(newSong)
    });
    const song = await response.json();

    if (response.ok) {
        dispatch(addSong(song));
        return song;
    }
};

export const removeSong = (songId) => ({
    type: REMOVE_SONG,
    songId,
});


export const deleteSong = (songId) => async (dispatch) => {
    console.log(songId, 'deleteSong song')
    const response = await csrfFetch(`/api/songs/${songId}`, {
        method: 'delete'
    });

    if (response.ok) {
        const song = await response.json();
        dispatch(removeSong(song.id));
    }
};



const initialState = { entries: {} };


const songReducer = (state = initialState, action) => {
    switch (action.type) {
        case LOAD_SONGS: {
            const newState = { ...state, entries: {} }
            action.songs.forEach(song => {
                newState.entries[song.id] = song
            })
            return newState
        }
        case ADD_SONG: {
            return {
                ...state,
                entries: {
                    ...state.entries,
                    [action.newSong.id]: action.newSong
                }
            }
        }
        case REMOVE_SONG: {
            const newState = { ...state, entries: { ...state.entries } };
            delete newState.entries[action.songId];
            return newState;
        }
        default:
            return state;
    }
};

export default songReducer;

Specifically I'm having trouble getting the specific song I want to delete. I can render the user's songs with the option to delete just fine but how should I tell it what song I'm specifically clicking on so it knows to delete. Also the state is not updating as well but I think that is related to my current issue. Any refactoring tips as well would be appreciated, this is my first react project. Thanks!

CodePudding user response:

...
const remove = (e) => {
        dispatch(deleteSong(e.target.id))
    }

...
    return (
        ...
        
       <button id={id} onClick={remove}>remove</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related