Home > database >  Change background color of selected div in a map function
Change background color of selected div in a map function

Time:08-08

I've mapped an array of objects to a div. I would like to change background color of the selected div in getNext12MonthsWithYear map function with useState. Currently on click, background color of all divs is changing, however I want to change only the selected div's background color. Here is what I have done so far :

import React, { useState } from "react";

const Test = () => {
  const [monthSelected, setMonthSelected] = useState(false);

  const selectMonth = (id) => {
    monthSelected ? setMonthSelected(false) : setMonthSelected(true);
    console.log(id);
  };

  function getNext12MonthsWithYear() {
    var now = new Date();
    var month = now.getMonth();
    var year = now.getFullYear();

    var names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

    var res = [];
    for (var i = 0; i < 12;   i) {
      res.push({ month: names[month]   " "   year, status: -1 });
      if (  month === 12) {
        month = 0;
          year;
      }
    }
    return res;
  }

  let upcomingMonths = getNext12MonthsWithYear();
  //   console.log(upcomingMonths);

  return (
    <div style={{ display: "flex", flexDirection: "row" }}>
      {upcomingMonths.map((upcomingMonth, id) => {
        return (
          <div
            key={id}
            id={id}
            onClick={() => selectMonth(id)}
            style={{
              width: "50px",
              height: "50px",
              border: "1px solid black",
              backgroundColor: monthSelected ? "green" : "white",
            }}
          >
            {upcomingMonth.month}
          </div>
        );
      })}
    </div>
  );
};

export default Test;

CodePudding user response:

Create a separate component for looping element. Complete code here

import { useState } from "react";

const NewCom = ({ id, upcomingMonth }) => {
  const [monthSelected, setMonthSelected] = useState(false);

  const selectMonth = (id) => {
    monthSelected ? setMonthSelected(false) : setMonthSelected(true);
    console.log(id);
  };

  return (
    <div
      id={id}
      onClick={() => selectMonth(id)}
      style={{
        width: "50px",
        height: "50px",
        border: "1px solid black",
        backgroundColor: monthSelected ? "green" : "white",
      }}
    >
      {upcomingMonth.month}
    </div>
  );
};

const Test = () => {
  function getNext12MonthsWithYear() {
    var now = new Date();
    var month = now.getMonth();
    var year = now.getFullYear();

    var names = [
      "January",
      "February",
      "March",
      "April",
      "May",
      "June",
      "July",
      "August",
      "September",
      "October",
      "November",
      "December",
    ];

    var res = [];
    for (var i = 0; i < 12;   i) {
      res.push({ month: names[month]   " "   year, status: -1 });
      if (  month === 12) {
        month = 0;
          year;
      }
    }
    return res;
  }

  let upcomingMonths = getNext12MonthsWithYear();
  console.log(upcomingMonths);

  return (
    <div style={{ display: "flex", flexDirection: "row" }}>
      {upcomingMonths.map((upcomingMonth, id) => (
        <NewCom key={id} id={id} upcomingMonth={upcomingMonth} />
      ))}
    </div>
  );
};

export default Test;

CodePudding user response:

Instead of having a boolean in state, you can store the id of selected month

const [monthSelected, setMonthSelected] = useState(null);

And while rendering the list set the id as monthSelected directly

<div
    key={id}
    id={id}
    onClick={() => setMonthSelected(id)}
    style={{
       width: "50px",
       height: "50px",
       border: "1px solid black",
       backgroundColor: monthSelected === id ? "green" : "white",
    }}
   >
    {upcomingMonth.month}
</div>

CodePudding user response:

I change useState to number:

const [monthSelected, setMonthSelected] = useState(null);

And compare current monthSelected with id:

backgroundColor: monthSelected === id ? "green" : "white"

Full solution:

import React, { useState } from "react";

const Test = () => {
  const [monthSelected, setMonthSelected] = useState(null);

  function getNext12MonthsWithYear() {
    var now = new Date();
    var month = now.getMonth();
    var year = now.getFullYear();

    var names = [
      "January",
      "February",
      "March",
      "April",
      "May",
      "June",
      "July",
      "August",
      "September",
      "October",
      "November",
      "December"
    ];

    var res = [];
    for (var i = 0; i < 12;   i) {
      res.push({ month: names[month]   " "   year, status: -1 });
      if (  month === 12) {
        month = 0;
          year;
      }
    }
    return res;
  }

  let upcomingMonths = getNext12MonthsWithYear();
  //   console.log(upcomingMonths);

  return (
    <div style={{ display: "flex", flexDirection: "row" }}>
      {upcomingMonths.map((upcomingMonth, id) => {
        return (
          <div
            key={id}
            id={id}
            onClick={() => setMonthSelected(id)}
            style={{
              width: "50px",
              height: "50px",
              border: "1px solid black",
              backgroundColor: monthSelected === id ? "green" : "white"
            }}
          >
            {upcomingMonth.month}
          </div>
        );
      })}
    </div>
  );
};

export default Test;

CodePudding user response:

You need to pass the id to the state to let your component know which is the current selected element. Right now, you have a boolean state which, if set to true, changes color of all the months. Try changing your code to the below code.

import React, { useState } from "react";

const Test = () => {
  const [monthSelected, setMonthSelected] = useState(false);

  const selectMonth = (id) => {
     setSelectedMonth(id)
  };

  function getNext12MonthsWithYear() {
    var now = new Date();
    var month = now.getMonth();
    var year = now.getFullYear();

    var names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

    var res = [];
    for (var i = 0; i < 12;   i) {
      res.push({ month: names[month]   " "   year, status: -1 });
      if (  month === 12) {
        month = 0;
          year;
      }
    }
    return res;
  }

  let upcomingMonths = getNext12MonthsWithYear();
  //   console.log(upcomingMonths);

  return (
    <div style={{ display: "flex", flexDirection: "row" }}>
      {upcomingMonths.map((upcomingMonth, id) => {
        return (
          <div
            key={id}
            id={id}
            onClick={() => selectMonth(id)}
            style={{
              width: "50px",
              height: "50px",
              border: "1px solid black",
              backgroundColor: id===monthSelected ? "green" : "white",
            }}
          >
            {upcomingMonth.month}
          </div>
        );
      })}
    </div>
  );
};

export default Test;

Alternatively, if you want to allow selecting multiple months, you would need to have as many states as there are months (12).

  • Related