unadlib / mutative

Efficient immutable updates, 2-6x faster than naive handcrafted reducer, and more than 10x faster than Immer.
http://mutative.js.org/
MIT License
1.56k stars 18 forks source link

Is it possible to use class instances with create? #46

Open fakalit opened 1 month ago

fakalit commented 1 month ago

Feeding class instances to create function causes the following Error, unless they are wrapped with a primitive like it's done in the class benchmark example.

Error: Invalid base state: create() only supports plain objects, arrays, Set, Map or using mark() to mark the state as immutable

Is this by design? What is the recommended usage pattern for mutating class instances?

unadlib commented 1 month ago

As mentioned in the error message, you can use the mark option function to mark immutable class instances. For example,

class Foobar {
  foo = {
    bar: 'str',
  };

  change() {
    this.foo.bar = 'new str';
  }
}

const data = {
  foo: {
    bar: 'str',
  },
  foobar: new Foobar(),
};

const state = create(
  data,
  (draft) => {
    draft.foo.bar = 'new str';
    draft.foobar.change();
  },
  {
    mark: (target, { immutable }) => {
      if (target instanceof Foobar) return immutable;
    },
  }
);
const foobar = new Foobar();
foobar.foo.bar = 'new str';
expect(state).toEqual({ foo: { bar: 'new str' }, foobar });
expect(state).not.toBe(data);
expect(state.foo).not.toBe(data.foo);
expect(state.foobar).not.toBe(data.foobar);
expect(state.foobar.foo).not.toBe(data.foobar.foo);