i am new to react and i am trying to mark one poem from a db.json file as read but clicking one affects all of the articles. how do i select only one at a time.
import React , {useState, useEffect} from "react";
function Poem() {
const [poemShow, setPoemShow] = useState([])
const PoemData = "http://localhost:8004/poems"
// to load the Poem
useEffect(() => {
fetch(PoemData)
.then((res) => res.json())
.then((data) => {setPoemShow(data)})
// .then((data) => console.log(data))
}, []);
const [unread, setUnread] = useState(false)
function markRead(event) {
console.log({unread, setUnread})
setUnread(!unread)
// console.log( `${item.id} marked`)
}
return (
<div>
{poemShow.map((item) => (
<div key={item.id}>
<h3>{item.title}</h3>
<p>{item.content}</p>
<strong>{item.author}</strong><br/>
{/* <button onClick={markRead}>{unread ? "Mark as unread" : "Mark as read" }</button> */}
<button onClick={(event) => markRead(event.target.id)}>{unread ? "Mark as unread" : "Mark as read" }</button>
<hr/>
</div>
))}
</div>
);
}
export default Poem;
CodePudding user response:
You could store an object instead, that maps an itemId
to a boolean
(true
or false
), meaning if the item with the given id is read or not:
const [readState, setReadState] = useState({})
Have an event handler like this (it's a function creating a function, that will be used as the event handler)
const toggleReadState = (itemId) => () => setReadState({ ...redState, [itemId]: !redState[itemId] })
And then render the list like this:
poemShow.map((item) => (
<div key={item.id}>
{/* ... */}
<button onClick={toggleReadState(item.id)}>{redState[item.id] ? 'Mark as unread' : 'Mark as read'}</button>
</div>
))
CodePudding user response:
When you are clicking on button, you are instantly changing all undread values from true to false and vice versa:
setUnread(!unread)
This might do the trick, because you need to filter out entry selected entry.
setUnread(unread.filter(el => el.id === event))