Home > database >  Changing State on Multiple React Elements in a Grid
Changing State on Multiple React Elements in a Grid

Time:12-28

I have a grid that has multiple buttons in it, the number of buttons varying by row. For example, row 1 could have 4 buttons, row 2 could have 3, row 3 could have 3, etc. I'm trying to make it to where when I click on one button, it changes not only its background color, but every button in the grid that also has the same text. So if my buttons kind of look like this:

[ text ]  [ moreText ]  [ someMoreText ]
[ texting]  [ textAgain ]  [text]
[textAgain] [ someMoreText]

The idea is that when I click on the button [ text ] in row 1, it'll also change the button in row 2 column 3 that is also [ text ].

Right now, I can get one button to change, but I'm stuck on getting the rest of them to change. Below is my code.

GridComponent.js

import React from "react";
import ButtonComponent from "./ButtonComponent";

const GridComponent = ({ arrayOfArray }) => {
  const renderColumns = (array) => {
    const columns = array.map((buttonText, index) => {
      return (
        <div key={index}>
          <div className="column">
            <ButtonComponent buttonText={buttonText} />
          </div>
        </div>
      );
    });
    return columns;
  };

  const renderRows = () => {
    const rows = arrayOfArry.map((array, index) => {
      return (
        <div key={index} className="row">
          {renderColumns(array)}
        </div>
      );
    });
    return rows;
  };

  return (
    <div>
      <div className="ui grid">{renderRows()}</div>
    </div>
  );
};

export default GridComponent;

ButtonComponent.js

import React, { useState } from "react";

const ButtonComponent = ({ buttonText }) => {
  const [status, setStatus] = useState(false);
  const color = status ? "green" : "blue";

  return (
    <div className={`ui ${color} button`} onClick={() => setStatus(!status)}>
      {buttonText}
    </div>
  );
};

export default ButtonComponent;

CodePudding user response:

You need to maintain the state at the GridComponent level, not on each ButtonComponent, which has no knowledge of other buttons.

You can do this by using a "map" object that maps the button text to its status.

const GridComponent = ({ arrayOfArray }) => {
  const [statuses, setStatuses] = useState({});
  ...

And pass this map and the update function to the ButtonComponent:

<ButtonComponent
   buttonText={buttonText}
   status={statuses}
   updateStatus={setStatuses}
/>

And in the ButtonComponent set the color bases on the status in the map for this button text:

const ButtonComponent = ({ buttonText, status, updateStatus }) => {
  const color = status[buttonText] ? "green" : "blue";

  return (
    <div
      className={`ui ${color} button`}
      onClick={() =>
        updateStatus({ ...status, [buttonText]: !status[buttonText] })
      }
    >
      {buttonText}
    </div>
  );
};

You can see how it works on codesandbox

  • Related