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>