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

[BUG] Immer Error when setting properties on a Record object #113

Closed
lautiab opened this issue Apr 6, 2023 · 5 comments
Closed

[BUG] Immer Error when setting properties on a Record object #113

lautiab opened this issue Apr 6, 2023 · 5 comments

Comments

@lautiab
Copy link

lautiab commented Apr 6, 2023

Description

When using the use-immer package with a reducer, I encountered a runtime error when trying to set a property on a Record<string, SomeType> object within the reducer function. The error message was:

[Immer] Immer only supports setting array indices and the 'length' property.

The exampleRecord object in my state is a Record<string, CustomType> and not an array, but it seems Immer might be interpreting the object as an array during its internal checks.

Code

Here is a simplified version of my reducer code:

export interface CustomType { /* ... */ }

export interface RecordData {
    id: string;
    label: string;
    exampleRecord: Record<string, CustomType>;
}

export interface ExampleState {
    tabData: RecordData[];
    /* ... */
}

const exampleReducer: ImmerReducer<ExampleState, ExampleAction> = (state, action) => {
    switch (action.type) {
        case ExampleActionTypes.ADD_PROPERTY: {
            const uniqueId = `id--${uuidv4()}`;

            state.tabData[state.selectedTab].exampleRecord[uniqueId] = {
                /* ... */
            };
            break;
        }
        /* ... */
    }
};

// In the component:
const [state, dispatch] = useImmerReducer(exampleReducer, initialState);

Workaround

Just in case it works for anybody facing the same, or to find the issue faster..

Creating a new object with the updated exampleRecord and then assigning it back to the draft state:

case ExampleActionTypes.ADD_PROPERTY: {
    const uniqueId = `id--${uuidv4()}`;
    const newObject: CustomType = { /* ... */ };

    state.tabData[state.selectedTab].exampleRecord = {
        ...state.tabData[state.selectedTab].exampleRecord,
        [uniqueId]: newObject,
    };
    break;
}

This workaround avoids the error, but it would be great if Immer could handle setting properties on Record objects without the need for this workaround.

@lautiab lautiab changed the title Immer Error when setting properties on a Record object [BUG] Immer Error when setting properties on a Record object Apr 6, 2023
@mweststrate
Copy link
Collaborator

mweststrate commented Apr 6, 2023 via email

@mweststrate
Copy link
Collaborator

mweststrate commented Apr 6, 2023 via email

@lautiab
Copy link
Author

lautiab commented Apr 6, 2023

I believe the error is not due to using a string index accessor with an array, but rather due to limitations of Immer when setting properties on Record objects directly.

For your information, selectedTab is of the number type, and the provided workaround wouldn't have worked if the issue was coming from there.

I'm using:
"immer": "^9.0.21",
"use-immer": "^0.8.1",
"typescript": "^4.9.3",

@mweststrate
Copy link
Collaborator

mweststrate commented Apr 6, 2023 via email

@lautiab
Copy link
Author

lautiab commented Apr 7, 2023

Hey again, I've been digging around and found that at initialization I was still using an array instead of an object. I believe TS was not failing at buildtime, cause I've messed up with the location of the Interface. Now it's working correctly, thanks for your help though!

@lautiab lautiab closed this as completed Apr 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants