Rk Shawon
Rk Shawon

Reputation: 17

Updating single item in react state hook

I have array useState hook which consists of items with className. I want to update className of a single item from that hook. How do I update single value of a useState hook.Of course I am going to put condition before updating . here is the code -

 display.map( word => 
   ( Words[leftPointer] === word.props.children ? 
      {...display, word:(<span key={uuid()} className="singleWord greenword"> 
      {Words[leftPointer]}</span>)} :
        display )
        )
 setDisplay(display)

here display contains array of span. what I want is go change the className based on the condition example- after updating the item className = "singleWord greenword" should be className="singleWord" of that item.

Upvotes: 0

Views: 170

Answers (3)

よつば
よつば

Reputation: 527

I would recommend against setting className in the state's domain as that is part of the UI's domain. Instead data changes can be used to signal responses in the UI rendering. This is what it means for a program to be data-driven.

Here is a minimal verifiable example. Run the program below and change some quantities to see the display state update. The className is automatically changed based on conditions applied to the application state.

function App() {
  const [display, setDisplay] = React.useState([
    {item: "walnut", quantity: 0 },
    {item: "peanut", quantity: 3 },
    {item: "donut", quantity: 6 }
  ])
  function update(index) { return event =>
    setDisplay([
      ...display.slice(0, index),
      { ...display[index], quantity: Number(event.target.value) },
      ...display.slice(index + 1)
    ])
  }   
  return <div>
    {display.map((d, index) =>
      <div key={index}>
        {d.item}:
        <input
          className={d.quantity > 0 ? "instock" : "outofstock" }
          value={d.quantity}
          onChange={update(index)}
        />
      </div>
    )}
    <div>{display.every(d => d.quantity > 0) ? "✅" : "❌"}</div>
    <pre>{JSON.stringify(display, null, 2)}</pre>
  </div>
}

ReactDOM.render(<App/>, document.querySelector("#app"))
input { outline: 0 }
.instock { border-color: limegreen; }
.outofstock { border-color: red; }
pre { padding: 0.5rem; background-color: #ffc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Upvotes: 1

Shambhu Sahu
Shambhu Sahu

Reputation: 341

Map function will return a new array so you just have to store the array in a new variable and set the state with that new variable

const newDisplay = display.map( (word) =>{ 
    if(Words[leftPointer] === word.props.children){
      return {word:(<span key={uuid()} className="singleWord greenword"> 
      {Words[leftPointer]}</span>)}
    }else{
        return word
    }
  })
  setDisplay(newDisplay)

Upvotes: 1

user18300050
user18300050

Reputation: 11

could you just use a state variable that holds the text for className and update that state variable on the useState hook to whatever you want?

Upvotes: 0

Related Questions