immerjs / use-immer

Use immer to drive state with a React hooks
MIT License
4.04k stars 92 forks source link

addition to docs #120

Closed nonopolarity closed 4 months ago

nonopolarity commented 1 year ago

I am not too familiar with useReducer yet, but it seems useImmer can support

setCount(c => c + 1) or setToggle(t => !t).

The current README doesn't say this but just say setCount(count + 1).

Also, the way to think about

updateData(draft => {
  draft.foo.bar.num += 10;
});

is just like

setData(data => {
  const newData = deepCopy(data);
  newData.foo.bar.num += 10;
  return newData;
});

not exactly that, I think, because I noticed while debugging you don't always do a deep copy if you don't need to.

So the rule seems to be: it is as if you do a deep copy, and then you can "mutate" it like there is no tomorrow with that new copy, and then setData(newData). That may be an easy way to think about. Maybe you can add it to the README if it can help some users.

Seize-cf commented 11 months ago

If you want to make this feature work, you gotta use Proxy and Reflect to update the value of the state in the set method.

const [value, setValue] = useState<T | undefined>()

const createProxy = (target: T): T => {
  return new Proxy(target, {
    get: Reflect.get,
    set: (target, key: keyof T, value, receiver) => {
      target[key] = value
      setValue(createProxy(target))
      return Reflect.set(target, key, value, receiver)
    }
  })
}

Update: ahooks now has a handy function called useReactive that you can refer to.