ashfaqrafi
ashfaqrafi

Reputation: 500

Select only one button from a list of buttons

I have a component which has several cards and each card has a button. Here is the component:

import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";

function ListItemComponent() {
  let [responseData, setResponseData] = useState([]);
  const [isFavorite, setIsFavorite] = useState(false);

  useEffect(() => {
    fetch("https://api.quotable.io/authors?limit=10&skip=20")
      .then((res) => res.json())
      .then((data) => {
        console.log(data.results);
        setResponseData(data.results);
      });
  }, []);

  console.log({ responseData });

  var testObject = { one: 1, two: 2, three: 3 };

  // Put the object into storage
  localStorage.setItem("testObject", JSON.stringify(testObject));

  // Retrieve the object from storage
  var retrievedObject = localStorage.getItem("testObject");

  console.log("retrievedObject: ", JSON.parse(retrievedObject));

  const handleClick = () => {
    setIsFavorite((s) => !s);
  };

  return (
    <div>
      <Container>
        <Row>
          {responseData && responseData.length > 0 ? (
            responseData.map((author) => {
              return (
                <Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
                  <Card>
                    <Card.Body>
                      <p>
                        <b>Name:</b> {author.name}
                      </p>
                      <p>
                        <b>Bio:</b> {author.bio}
                      </p>
                      <a href={author.link}>Link</a>
                      {isFavorite ? (
                        <Button variant="danger" onClick={handleClick}>
                          Remove Favorite
                        </Button>
                      ) : (
                        <Button variant="success" onClick={handleClick}>
                          Add Favorite
                        </Button>
                      )}
                    </Card.Body>
                  </Card>
                </Col>
              );
            })
          ) : (
            <p>No Data Found</p>
          )}
        </Row>
      </Container>
    </div>
  );
}

export default ListItemComponent;

here is a gif of what is happening now:https://recordit.co/C8gUJ0ByRY. So now if I click on just one button all the buttons in all the cards get selected and changes to Remove Favorite from Add Favorite, but I want to change the text of the only button that is clicked not all of them.

Upvotes: 0

Views: 225

Answers (3)

Calebe Fazzani
Calebe Fazzani

Reputation: 71

In your actual code, the isFavorit variable is used in all the elements of the list. You can change to this to make each object of the list possess the isFavorit variable and, this way, only the ones with isFavorite = true will change.

import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";

function ListItemComponent() {
  let [responseData, setResponseData] = useState([]);

  useEffect(() => {
    fetch("https://api.quotable.io/authors?limit=10&skip=20")
      .then((res) => res.json())
      .then((data) => {
        console.log(data.results);
        setResponseData(data.results.map((result) => ({...result,isFavorite:false})));
      });
  }, []);

  console.log({ responseData });

  var testObject = { one: 1, two: 2, three: 3 };

  // Put the object into storage
  localStorage.setItem("testObject", JSON.stringify(testObject));

  // Retrieve the object from storage
  var retrievedObject = localStorage.getItem("testObject");

  console.log("retrievedObject: ", JSON.parse(retrievedObject));

  const handleClick = (a) => {
    const author = responseData.find(el => el._id === a._id);
    author.isFavorite = !author.isFavorite;
    const list = responseData.map(el => author._id === el._id ? author : el );
    setResponseData(list);
    // setIsFavorite((s) => !s);
  };

  return (
    <div>
      <Container>
        <Row>
          {responseData && responseData.length > 0 ? (
            responseData.map((author) => {
              return (
                <Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
                  <Card>
                    <Card.Body>
                      <p>
                        <b>Name:</b> {author.name}
                      </p>
                      <p>
                        <b>Bio:</b> {author.bio}
                      </p>
                      <a href={author.link}>Link</a>
                      {author.isFavorite ? (
                        <Button variant="danger" onClick={() => handleClick(author)}>
                          Remove Favorite
                        </Button>
                      ) : (
                        <Button variant="success" onClick={() => handleClick(author)}>
                          Add Favorite
                        </Button>
                      )}
                    </Card.Body>
                  </Card>
                </Col>
              );
            })
          ) : (
            <p>No Data Found</p>
          )}
        </Row>
      </Container>
    </div>
  );
}

export default ListItemComponent;

Upvotes: 1

Soufiane Boutahlil
Soufiane Boutahlil

Reputation: 2604

You should create an array of favorites, each item on the array will be connected with a button, like this:

const [favorites, setFavorites] = useState(Array(responseData.length).fill(false));

And when you click on button, you will send the index clicked button to toggle the favourite of the button:

 const handleClick = (index) => {
    setFavorites((favorites) => favorites.map((favorite, i) => {
            if(i == index) return !favorite
            else return favorite
   }));
  };

Your component:

import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";

function ListItemComponent() {
  let [responseData, setResponseData] = useState([]);

const [favorites, setFavorites] = useState(Array(responseData.length).fill(false));

  useEffect(() => {
    fetch("https://api.quotable.io/authors?limit=10&skip=20")
      .then((res) => res.json())
      .then((data) => {
        console.log(data.results);
        setResponseData(data.results);
      });
  }, []);

  console.log({ responseData });

  var testObject = { one: 1, two: 2, three: 3 };

  // Put the object into storage
  localStorage.setItem("testObject", JSON.stringify(testObject));

  // Retrieve the object from storage
  var retrievedObject = localStorage.getItem("testObject");

  console.log("retrievedObject: ", JSON.parse(retrievedObject));

 const handleClick = (index) => {
    setFavorites((favorites) => favorites.map((favorite, i) => {
            if(i == index) return !favorite
            else return favorite
   }));
  };

  return (
    <div>
      <Container>
        <Row>
          {responseData && responseData.length > 0 ? (
            responseData.map((author,i) => {
              return (
                <Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
                  <Card>
                    <Card.Body>
                      <p>
                        <b>Name:</b> {author.name}
                      </p>
                      <p>
                        <b>Bio:</b> {author.bio}
                      </p>
                      <a href={author.link}>Link</a>
                      {favorites[i] ? (
                        <Button variant="danger" onClick={handleClick}>
                          Remove Favorite
                        </Button>
                      ) : (
                        <Button variant="success" onClick={handleClick}>
                          Add Favorite
                        </Button>
                      )}
                    </Card.Body>
                  </Card>
                </Col>
              );
            })
          ) : (
            <p>No Data Found</p>
          )}
        </Row>
      </Container>
    </div>
  );
}

export default ListItemComponent;

Upvotes: 0

ashfaqrafi
ashfaqrafi

Reputation: 500

import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";

function ListItemComponent() {
  let [responseData, setResponseData] = useState([]);
  const [isFavorite, setIsFavorite] = useState(false);
  const [index, setIndex] = useState(false);

  useEffect(() => {
    fetch("https://api.quotable.io/authors?limit=10&skip=20")
      .then((res) => res.json())
      .then((data) => {
        console.log(data.results);
        setResponseData(data.results);
      });
  }, []);

  console.log({ responseData });

  var testObject = { one: 1, two: 2, three: 3 };

  // Put the object into storage
  localStorage.setItem("testObject", JSON.stringify(testObject));

  // Retrieve the object from storage
  var retrievedObject = localStorage.getItem("testObject");

  console.log("retrievedObject: ", JSON.parse(retrievedObject));

  const handleClick = (id) => {
    setIsFavorite((s) => !s);
    setIndex(id);
    console.log(id);
  };

  return (
    <div>
      <Container>
        <Row>
          {responseData && responseData.length > 0 ? (
            responseData.map((author) => {
              return (
                <Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
                  <Card>
                    <Card.Body>
                      <p>
                        <b>Name:</b> {author.name}
                      </p>
                      <p>
                        <b>Bio:</b> {author.bio}
                      </p>
                      <a href={author.link}>Link</a>
                      {isFavorite && index === author.link ? (
                        <Button
                          variant="danger"
                          onClick={() => handleClick(author.link)}
                        >
                          Remove Favorite
                        </Button>
                      ) : (
                        <Button
                          variant="success"
                          onClick={() => handleClick(author.link)}
                        >
                          Add Favorite
                        </Button>
                      )}
                    </Card.Body>
                  </Card>
                </Col>
              );
            })
          ) : (
            <p>No Data Found</p>
          )}
        </Row>
      </Container>
    </div>
  );
}

export default ListItemComponent;

Upvotes: 0

Related Questions