Home > Software engineering >  react- click and event affects only one item on a list
react- click and event affects only one item on a list

Time:07-25

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))

  • Related