Mutated state in Valtio isn't reset when you assign a new object?

175 Views Asked by At

I have saved objects that can be selected as active. When they are "active" the value can be incremented:

import { proxy, useSnapshot } from "valtio";

const first = {
  name: "First",
  value: 1
};
const second = {
  name: "Second",
  value: 2
};
const initState = {
  active: first,
  saved: [first, second]
};
const store = proxy(initState);

export default function App() {
  const snap = useSnapshot(store);
  return (
    <div>
      <h2>Active:</h2>
      <p>Name: {snap.active.name}</p>
      <p>Value: {snap.active.value}</p>
      <button onClick={()=>store.active.value++}>Increment</button>
      <br />
      <h2>Options:</h2>
      <ul>
        {snap.saved.map((item) => {
          return (
            <li key={item.name} onClick={()=> store.active = item}>
              {item.name} - {item.value}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

https://codesandbox.io/s/confident-wildflower-d43w8r?file=/src/App.js

This is the initial status:

enter image description here

If I click on second option it's selected as active:

enter image description here

If I click the increment button it's value becomes 3:

enter image description here

If I click the first option Im back at the initial status:

enter image description here

And now here is the surprise. If I click the second option it "remembers" the value was changed to 3. However what I need is for the value to have been reset to it's original value of 2.

enter image description here

I've also made a screen recording of these steps: https://www.loom.com/share/0f11ba769f2a403dbf867b0cca315afa

How can I make it so when you mutate state it's always only the active object that changes? And when you select a saved object it will always have it's original value?

1

There are 1 best solutions below

1
Evanss On BEST ANSWER

Not sure if this is best practice but it can be fixed with lodash's cloneDeep

import cloneDeep from 'lodash/cloneDeep';

<li key={item.name} onClick={() => store.active = cloneDeep(item)}>