Kaiser91
Kaiser91

Reputation: 343

How to set state in nested object

Would like to know if there is a way to update nested object states in React using useState()

import React, {useState} from 'react'

const MyComp = () => {

  const [colors, setColors] = useState({colorA: 'RED', colorB: 'PURPLE'});

  return (
    <div>
       <span>{colors.colorB}</span>
       <button onClick={() => setColors({...colors, colors: { colorB: 'WHITE'}})}>CLICK ME</button>
    </div>
  )
}


export default MyComp;

I was thinking to use useReducer() but I read that It's normally use for more complex states and maybe there is a solution for this case just using useState()

Any ideas?

Thx in advance

Upvotes: 2

Views: 306

Answers (6)

Snivio
Snivio

Reputation: 1864

There was a minor syntax error in the statement

 const App = () => {


  const [colors, setColors] = useState({ colorA: 'RED', colorB: 'PURPLE' });

  return (
    <div>
      <span>{colors.colorB}</span>
      <button onClick={
        () =>
          setColors(
            { ...colors,colorB: 'WHITE' }
          )
      }>CLICK ME</button>
    </div>
  )
}

Upvotes: 0

Beginner
Beginner

Reputation: 9135

Since you have already done the spread, it will have the property colorB, you just need to update with new value

const handleButtonClick = () => {
    setColors({ ...colors, colorB: "WHITE" });
  };

making it into a function will be more readable.

Code

import React, { useState } from "react";
import ReactDOM from "react-dom";

const MyComp = () => {
  const [colors, setColors] = useState({ colorA: "RED", colorB: "PURPLE" });

  const handleButtonClick = () => {
    setColors({ ...colors, colorB: "WHITE" });
  };

  return (
    <div>
      <span>{colors.colorB}</span>
      <button onClick={handleButtonClick}>CLICK ME</button>
    </div>
  );
};

export default MyComp;

const rootElement = document.getElementById("root");
ReactDOM.render(<MyComp />, rootElement);

Working Codepen

Upvotes: 2

Simon Gomes
Simon Gomes

Reputation: 383

USE

setColors({...colors, colorB: 'WHITE'})

INSTEAD OF

setColors({...colors, colors: { colorB: 'WHITE'}})

Upvotes: 4

Clarity
Clarity

Reputation: 10873

It's better to use functional form of setState for this, since the next state value depends on the current value of the state:

 return (
    <div>
      <span>{colors.colorB}</span>
      <button
        onClick={() => setColors(currentColors => ({ ...currentColors, colorB: "WHITE" }))}
      >
        CLICK ME
      </button>
    </div>
  );

Upvotes: 3

Gangadhar Gandi
Gangadhar Gandi

Reputation: 2252

You are updating the state in a wrong way. Change your button statement to below,

<button onClick={() => setColors({...colors, colorB: 'WHITE'})}>CLICK ME</button>

Upvotes: 4

Dupocas
Dupocas

Reputation: 21357

colors already is the whole object, you don't need to declare as a property.

spread the original object and override colorB

() => setColors({...colors, colorB: 'WHITE'}) 

Upvotes: 4

Related Questions