-
Notifications
You must be signed in to change notification settings - Fork 95
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
Comments
Immer doesn't see arrays where they aren't. One of the index accessors in
your code might actually be a string instead of a number. Pretty sure
you're making a mistake somewhere in there, but hard to tell without a
repro.
…On Thu, 6 Apr 2023, 23:17 lautiAB, ***@***.***> wrote:
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.
—
Reply to this email directly, view it on GitHub
<#113>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBCKJBSUHWUVKBQIPDTW74XHFANCNFSM6AAAAAAWV4TPSY>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
E.g. state.selectTab is probably the issue, not the uniqueId?
…On Thu, 6 Apr 2023, 23:24 Michel Weststrate, ***@***.***> wrote:
Immer doesn't see arrays where they aren't. One of the index accessors in
your code might actually be a string instead of a number. Pretty sure
you're making a mistake somewhere in there, but hard to tell without a
repro.
On Thu, 6 Apr 2023, 23:17 lautiAB, ***@***.***> wrote:
> 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.
>
> —
> Reply to this email directly, view it on GitHub
> <#113>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAN4NBCKJBSUHWUVKBQIPDTW74XHFANCNFSM6AAAAAAWV4TPSY>
> .
> You are receiving this because you are subscribed to this thread.Message
> ID: ***@***.***>
>
|
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: |
Record is not an object, it's a type, it doesn't exists at runtime, so it
doesn't relate to what immer can and cannot handle. So it seems that there
is something not correct in your application, but you'll need to repro
otherwise one can't help with that.
…On Fri, 7 Apr 2023, 00:11 lautiAB, ***@***.***> wrote:
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",
—
Reply to this email directly, view it on GitHub
<#113 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBFFKZJN45UC2ORIBSLW745Q3ANCNFSM6AAAAAAWV4TPSY>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
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! |
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:
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:
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:
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.
The text was updated successfully, but these errors were encountered: