简体   繁体   中英

React: How to Pass State on Each Mapped Array Items?

I rendered a list of buttons using Array.map method in a function component. When I tried to pass state to each mapped array items, the rendered results changed all array items at once, instead of one by one.

Here is my code. Am I doing something wrong? Sorry if the question has been solved in other thread or I used the wrong method. This is my first React project and I am still learning. It would be very appreciated if someone could advise. Thank you!

import React, { useState } from "react"

export default function Comp() {
  const [isActive, setActive] = useState(false)

  const clickHandler = () => {
    setActive(!isActive)
    console.log(isActive)
  }

  const data = [
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
    { id: 3, name: "Charlie" },
  ]

  const renderList = items => {
    return items.map(item => (
      <li key={item.id}>
        <button onClick={clickHandler}>
          {item.name} {isActive ? "active" : "not active"}
        </button>
      </li>
    ))
  }

  return (
    <ul>{renderList(data)}</ul>
  )
}

Put the individual item into a different component so that each has its own active state:

export default function Comp() {
  const data = [
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
    { id: 3, name: "Charlie" },
  ]

  const renderList = items => (
    items.map(item => <Item key={item.id} name={item.name} />)
  );

  return (
    <ul>{renderList(data)}</ul>
  )
}
const Item = ({ name }) => {
  const [isActive, setActive] = useState(false);
  const clickHandler = () => {
    setActive(!isActive);
  };
   return (
    <li>
      <button onClick={clickHandler}>
        {name} {isActive ? "active" : "not active"}
      </button>
    </li>
  );
};

You need to set the active-id in handling the click-event . That will in-turn render active/non-active conditionally :

Notice the flow (1) > (2) > (3)

function Comp() {
  const [activeId, setActiveId] = React.useState(null);
  const clickHandler = (item) => {
    setActiveId(item.id) // (2) click-handler will set the active id
  }

  const data = [
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
    { id: 3, name: "Charlie" },
  ]

  const renderList = items => {
    return items.map(item => (
      <li key={item.id}>
        <button onClick={() => clickHandler(item)}> // (1) passing the clicked-item so that we can set the active-id
          {item.name} {item.id === activeId ?
            "active" : "not active" // (3) conditionally render
          }
        </button>
      </li>
    ))
  }

  return (
    <ul>{renderList(data)}</ul>
  )
}

Good Luck...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM