mottosson
mottosson

Reputation: 3783

Why doesn't spread attributes work with React useState hook

I'm keeping state in a functional component using the useState hook and want to update a single value without having to explicitly set all other attributes, so I thought using the spread operator would work, but it does not!

This is my state:

const [state, setState] = useState({
  data: [],
  currentIndex: 0,
  editMode: false
});

Can someone explain why this doesn't work...

setState({ editMode: value, ...state });

...when this does:

setState({ editMode: value, data: [], currentIndex: 0 });

Whats the difference? Can I use the spread operator or have I misunderstood something?

Here is a CodeSandbox example to demonstrate the issue.

Upvotes: 1

Views: 1198

Answers (4)

Nick Parsons
Nick Parsons

Reputation: 50913

Doing { editMode: value, ...state } is equivelent to:

{                                   {
  editMode: value,                    
  data: [],                           data: [],
  currentIndex: 0,      ------->      currentIndex: 0,
  editMode: false                     editMode: false
}                                   }

As keys cannot be repeated in objects, the last editMode key-value pair overwrites the first, thus removing the first editMode: value. Instead, you can spread first:

{...state, editMode: value}

This will overwrite the editMode in your state with the new object editMode:

{                                   {
  data: [],                           data: [],
  currentIndex: 0,                    currentIndex: 0,
  editMode: false,      ------->      
  editMode: value,                    editMode: value,
}                                   }

Upvotes: 2

norbitrial
norbitrial

Reputation: 15166

It's all about the order. Think about the following:

const state = {
  data: [],
  currentIndex: 0,
  editMode: false
};
const value = true;

const result = { editMode: value, ...state };
const result2 = { editMode: value, data: [], currentIndex: 0 };
const result3 = { ...state, editMode: value };

console.log(result);
console.log(result2);
console.log(result3);

I hope that helps!

Upvotes: 3

Sushmit Sagar
Sushmit Sagar

Reputation: 1508

To update the Object with useState hook use this function syntax:

setState(prevState => ({ ...prevState, editMode: value }));

Upvotes: 0

user9408899
user9408899

Reputation: 4540

Just reverse the order:

setState({ ...state, editMode: value });

Otherwise, you are overwriting editMode's value with the old value.

Upvotes: 1

Related Questions