I'm having a simple component which is supposed to return all messages in database.
const axios = require('axios');
const _ = require('lodash');
const ChatList = () => {
const [messages, setMessages] = useState([]);
const [err, setErr] = useState('');
useEffect(() => {
const fetchMessages = async () => {
const allMessages = await axios.get('http://localhost:5000/chat');
const messagesMapped = Object.keys(allMessages.data)
.map((id) => allMessages.data[id])
.map((message) => _.omit(message, '_id'))
.map((message) => ({
...message,
delete: (
<Button
label="Delete"
className="p-button-outlined p-button-danger"
onClick={() => handleDelete(message.id)}
/>
),
}));
setMessages(messagesMapped);
};
fetchMessages();
}, []);
const handleDelete = (id) => {
axios
.delete(`http://localhost:5000/chat/${id}`)
.then((res) => alert(res.data[0]))
.then(() =>
setMessages((messages) =>
messages.filter((message) => message.id !== id)
)
)
.catch((err) => setErr(err.response.data));
};
console.log(messages);
return (
<div>
<Menu />
<div className="chat-list-div">
{err && <h1>{err}</h1>}
<DataTable value={messages} responsiveLayout="scroll">
<Column field="id" header="Id of message" />
<Column field="user" header="User" />
<Column field="message" header="Message" />
<Column field="delete" header="Operations" />
</DataTable>
</div>
</div>
);
};
export default ChatList;
I'm a bit confused, because if I write inside handleDelete in axios:
setMessages(messages.filter(message => message.id !== id)))
it seems to return empty array so my DataTable becomes empty.
It works fine if I write it like this:
setMessages(messages => messages.filter(message => message.id !== id)))
The problem is that I don't understand why it works with the 2nd option and does not with the 1st one. I've been using React for half a year and have always written the 1st option and it always WORKED. For example, I have another component which returns games, and the same logic works fine.
const [games,setGames] = useState('')
const handleDelete = (id) => {
axios.delete(`http://localhost:5000/games/${id}`)
.then((res) => alert(res.data[0]))
.then(() => setGames(games.filter(game => game.id !== id)))
.catch(err => setErr(err.response.data))
}
...
{games && games.map(game => (
<p>{game.id}</p>
))}
Is someone able to make me understand why in 2nd component it (making only setState(prevState.filter), not setState(prevState => prevState.filter) works and in 1st it doesn't?
//edit
Another component (GamesList):
import React, { useEffect, useState } from 'react';
import Menu from '../main/Menu';
import { Card } from 'primereact/card';
import { Button } from 'primereact/button';
const axios = require('axios');
const _ = require('lodash');
const GamesList = () => {
const [games, setGames] = useState([]);
useEffect(() => {
const fetchGames = async () => {
const allGames = await axios.get('http://localhost:5000/games');
const gamesMapped = Object.keys(allGames.data)
.map((id) => allGames.data[id])
.map((game) => _.omit(game, '_id'));
setGames(gamesMapped);
};
fetchGames();
}, []);
console.log(games);
const [err, setErr] = useState('');
const handleDelete = (id) => {
console.log(games);
axios
.delete(`http://localhost:5000/games/${id}`)
.then((res) => alert(res.data[0]))
.then(() => setGames(games.filter((game) => game.id !== id)))
.catch((err) => setErr(err.response.data));
};
const header = (
<img
alt="Card"
src="images/usercard.png"
onError={(e) =>
(e.target.src =
'https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png')
}
/>
);
const footer = (gameId) => (
<span>
<Button
label="Delete"
icon="pi pi-times"
className="p-button-outlined p-button-danger"
onClick={() => handleDelete(gameId)}
/>
</span>
);
return (
<div className="gameslist-main">
<Menu />
<div className="gameslist-cards">
{games &&
games.map((game) => (
<Card
title={game.id}
key={game.id}
subTitle="Game"
style={{ width: '25em' }}
footer={footer(game.id)}
header={header}
>
<h3>Winning numbers: {game.winningNumbers.toString()}</h3>
<p>
Players:{' '}
{game.players.toString().length === 0 ? (
<span>NONE</span>
) : (
<ul>
{game.players.map((player) => (
<li key={player.login} className="gameslist-card-player">
<span className="gameslist-card-player-span">
{player.login}
</span>
<span className="gameslist-card-player-span">
({player.numbers.toString()})
</span>
<span className="gameslist-card-player-span">
<span className="guessed-numbers">
{
game.winningNumbers
.toString()
.split(',')
.filter((num) =>
player.numbers
.toString()
.split(',')
.includes(num)
).length
}
</span>
</span>
<span className="gameslist-card-player-span">
<span className="separator">/</span>
</span>
<span className="gameslist-card-player-span">
<span className="no-guessed-numbers">5</span>
</span>
</li>
))}
</ul>
)}
</p>
{err && <p>err</p>}
</Card>
))}
</div>
</div>
);
};
export default GamesList;