Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify that the first result from the producer is not immutable unless a change is made #412

Closed
rickmugridge opened this issue Aug 25, 2019 · 7 comments · Fixed by #417, node-gh/gh#728 or boardgameio/boardgame.io#796

Comments

@rickmugridge
Copy link

rickmugridge commented Aug 25, 2019

🚀 Feature Proposal

As expected, when the producer is first applied to an object (or array) and a change is made, an immutable object results. However, if no such change is made, the result is mutable.

Motivation

Docs are unclear on this matter. I suggest that it would be better to make the result immutable regardless. But if that doesn't work, it would be good for the docs to be clear on this matter.

With the current implementation, I'm forced to make an arbitrary change to the object to make sure that it is immutable immediately.

Example

    it("Simple object becomes immutable as the produce() call made a change", () => {
        const c = {id: 3};
        const immutable = produce(c, draft => {
            draft.id = 4;
        });
        expect(c.id).eql(3);
        expect(immutable.id).eql(4);
        expect(() => (immutable as any).id = 5).to.throw("");
    });

    it("Simple object is not made immutable as the produce() call made no change", () => {
        const c = {id: 3};
        const immutable = produce(c, draft => {
        });
        (immutable as any).id = 4;
        expect(immutable.id).eql(4);
    });
@rickmugridge rickmugridge changed the title Clarify that the result from the producer is not immutable unless a change is made Clarify that the first result from the producer is not immutable unless a change is made Aug 25, 2019
@rickmugridge
Copy link
Author

Immer is a great and convenient structure-sharing system, but does not confer immutability except at points of change. Here's another example that illustrates this:

    it("Parts of simple object becomes immutable as the produce() call made a change", () => {
        interface D {
            a: { b: number };
            z: { y: number };
        }

        const d: D = {a: {b: 2}, z: {y: 3}};
        const immutable = produce(d, draft => {
            draft.a.b = 1;
        });
        expect(() => immutable.a.b = 5).to.throw("");
        immutable.z.y = 4;
        expect(immutable.z.y).eql(4);
    });

@mweststrate
Copy link
Collaborator

Although the freezing itself is not really the point of immer (there are separate packages for that), it seems a lot of peepz expect a full freeze from immer. To avoid more confusion in the future, a PR is welcome :)

@rickmugridge
Copy link
Author

rickmugridge commented Sep 2, 2019

I'm happy to (recursively) pre-freeze. Is it worth mentioning your favourite one in the docs, near the start to ensure immutability? I'll be more than satisfied with that.
Thanks.

@mweststrate
Copy link
Collaborator

A PR is welcome, but not urgent, I hope to get around to implement the change anyway in a couple of weeks, as it would be the least suprising behavior it seems in general :)

@ianstormtaylor
Copy link
Contributor

@mweststrate can you clarify what change you're thinking of making? I also expected that produce always returns deeply frozen objects. Are you thinking of changing to make that so? Or just changing the docs to have a warning?

@mweststrate
Copy link
Collaborator

mweststrate commented Sep 9, 2019 via email

mweststrate added a commit that referenced this issue Sep 11, 2019
…ply frozen.

BREAKING CHANGE: any value returned from produce will be deeply frozen in DEV, even when it wasn't frozen before the producer started. Fixes #412 #363 #260 #230 #313 #229 through #417
@aleclarson
Copy link
Member

🎉 This issue has been resolved in version 4.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment