Closed lautiab closed 1 year ago
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 https://github.com/immerjs/use-immer/issues/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 https://github.com/immerjs/use-immer/issues/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: "immer": "^9.0.21", "use-immer": "^0.8.1", "typescript": "^4.9.3",
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 https://github.com/immerjs/use-immer/issues/113#issuecomment-1499686956, 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.