0

I'm trying to figure how to update the a single element in a react .map. I want to add a selected state to my react button but right now its adding the selected state to all my buttons. I'm not sure how to go about this and wondering if someone could help me out please.

I've put to together a codeandsandbox to demonstrate what is happening, I'm trying to do this in the Dashboard.jsx page in the handleButtonClick function, I know it will need to take in an id but at this point I'm not sure what else.

import React, { useEffect, useState } from 'react';
import PropTypes from "prop-types";
import Item from './Item';
import { fetchData } from '../api/fetcher';

const Dashboard = () => {

  const [response, setResponse] = useState([]); 
  const [isSelected, setIsSelected] = useState(false); 
  //call data on page load
  useEffect(() => {
      fetchData(setResponse);
  }, [])

console.log(response);

const handleButtonClick = (id) => {

  setIsSelected(!isSelected)
}

  return (
    <React.Fragment>
      {response.map(items => 
        <Item 
          prodId={items.productId}
          key={items.productId}
          image={items.imageUrl}
          description={items.description}
          itemName={items.name}
          discount={items.promotionBadge}
          price={items.price}
          priceWas={items.priceWas}
          selected={isSelected}
          onClick={() => handleButtonClick(items.productId)}
        />
      )}
    </React.Fragment>
  );
}

export default Dashboard;

the setIsSelected(!isSelected) applies the style to all the buttons.

Here is my code and how it works:

https://codesandbox.io/s/charming-butterfly-vy6v8?file=/src/App.js

1

5 Answers 5

2

Move your isSelected state from Dashboard to Item component so that each Item list will have its own state.

I have made the changes you can check below.

https://codesandbox.io/s/billowing-snowflake-zibyf?file=/src/components/Item.jsx

Sign up to request clarification or add additional context in comments.

Comments

2

You could track which one is selected by holding the selected productId or Id's if multiple in the state and then selected would be just..

selected={items.productId === selectedProductId}

or

selected={selectedProductIds.includes(item.productId)}

This would also make it easier when you actually need to do something with the selected products.

Comments

1

you have to move useState and handleButtonClick inside Item, so every item has its useState and handleButtonClick. I've corrected it in sandbox for you. I also edited the className attribute for button item because they were twisted. sanbox

Comments

0

https://codesandbox.io/s/clever-morning-iqm7q

I've make some changes in your solutions. Your useState have to be unique for every items.

Comments

-1

Your variable selectedId was passed to all items with only one value. Please see my comment inside code: // <<<<<<<------------ SEE ME

import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import Item from "./Item";
import { fetchData } from "../api/fetcher";

const Dashboard = () => {
  const [response, setResponse] = useState([]);
  const [selectedId, setSelectedId] = useState(); // <<<<<<<------------ SEE ME
  //call data on page load
  useEffect(() => {
    fetchData(setResponse);
  }, []);

  console.log(response);

  const handleButtonClick = (id) => {
    setSelectedId(id); // <<<<<<<------------ SEE ME
  };

  return (
    <React.Fragment>
      {response.map((items) => (
        <Item
          prodId={items.productId}
          key={items.productId}
          image={items.imageUrl}
          description={items.description}
          itemName={items.name}
          discount={items.promotionBadge}
          price={items.price}
          priceWas={items.priceWas}
          selected={selectedId === items.productId} // <<<<<<<------------ SEE ME
          onClick={() => handleButtonClick(items.productId)}
        />
      ))}
    </React.Fragment>
  );
};

export default Dashboard;

1 Comment

This points out the problem, but doesn't answer the question. Please include an answer here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.