Home > database >  Trying to select a specific element. How do I change all other elements that aren't selected to
Trying to select a specific element. How do I change all other elements that aren't selected to

Time:11-03

Im trying to build a select function for my object. The issue is when I click another element the other elements remain selected.

How can I set all other elements to isSelected: false, after selecting the element I want.

I need a way so that when I set the state of the element I want to true, it will set all other element states to false.

import "./styles.css";
import { useEffect, useState } from "react";

// The parent component
const App = () => {
  const [textBoxDivs, setTextBoxDivs] = useState({});

  const addNewTextBox = () => {
    const numOfTextBoxDivs = Object.keys(textBoxDivs).length;
    console.log(numOfTextBoxDivs, "num");
    setTextBoxDivs({
      ...textBoxDivs,
      [`div${numOfTextBoxDivs   1}`]: {
        isSelected: false,
        innerText: "text"
      }
    });
  };

  const selectItem = (e) => {
    if (e) {
      const selectedItemKey = e.target.id;
      setTextBoxDivs({
        ...textBoxDivs,
        [selectedItemKey]: {
          ...textBoxDivs[selectedItemKey],
          isSelected: true
        }
      });
    }
  };

  return (
    <div>
      <button onClick={() => addNewTextBox()}>
        Click me to create a selectable div
      </button>

      {Object.keys(textBoxDivs).length > 0 &&
        Object.keys(textBoxDivs).map((key, index) => {
          return (
            <div
              style={{
                border: textBoxDivs[key].isSelected
                  ? "2px solid green"
                  : "unset"
              }}
              onClick={(e) => selectItem(e)}
              key={index}
              id={key}
            >
              {textBoxDivs[key].innerText}
            </div>
          );
        })}
    </div>
  );
};

export default App;

codesandbox: https://codesandbox.io/s/friendly-water-wf4f5?file=/src/App.js:0-1385

CodePudding user response:

To start, e will be defined, so no need to check it.

I would do something like this:

const selectItem = (e) => {

  const selectedItemKey = e.target.id;

  const nextState = {...textBoxDivs}
  Object.keys(nextState).forEach(k => {
     nextState[k].isSelected = false
  })

  nextState[selectedItemKey].isSelected = true

  setTextBoxDivs(nextState);
};

I haven't tested this.

CodePudding user response:

I would implement it with a selected state object, so each div only needs to check whether or not it's the selected one.

Add a state object to keep track of selected

const [selected, setSelected] = useState();

Change the ternary operator to selected == key ? "2px solid green" : "unset". Also, change your onClick to () => setSelected(key)

<div
  style={{
    border: selected == key ? "2px solid green" : "unset"
  }}
  onClick={() => setSelected(key)}
  key={index}
  id={key}
>

Then remove your selectItem() function.

Here's the full code:

const App = () => {
  const [textBoxDivs, setTextBoxDivs] = useState({});
  const [selected, setSelected] = useState();

  const addNewTextBox = () => {
    const numOfTextBoxDivs = Object.keys(textBoxDivs).length;
    console.log(numOfTextBoxDivs, "num");
    setTextBoxDivs({
      ...textBoxDivs,
      [`div${numOfTextBoxDivs   1}`]: {
        isSelected: false,
        innerText: "text"
      }
    });
  };

  return (
    <div>
      <button onClick={() => addNewTextBox()}>
        Click me to create a selectable div
      </button>

      {Object.keys(textBoxDivs).length > 0 &&
        Object.keys(textBoxDivs).map((key, index) => {
          return (
            <div
              style={{
                border: selected === key ? "2px solid green" : "unset"
              }}
              onClick={() => setSelected(key)}
              key={index}
              id={key}
            >
              {textBoxDivs[key].innerText}
            </div>
          );
        })}
    </div>
  );
};

export default App;

I think this will make your code more readable, and it reduces the number of lines you'll need to achieve the desired effect by completely removing the need for your selectItem function.

  • Related