1

I have a array and each element in the Array can be an array of cars ICar[], I am having issues adding an item to the list

const [carList, setCarList] = React.useState<[ICar[]]>([[]]);

When it comes to setting the state normally if it was a array of objects I would do the following

setCarList(initialList => [...initialList, JSON.parse(JSON.stringify(car))]); // this works when its just an array of ICar

But when I make it [ICar[]] I have issues

const cars =  [JSON.parse(JSON.stringify(car))] as ICar[];
setCarList(initialList => [[...initialList],cars]);
MicroMan
  • 1,988
  • 4
  • 32
  • 58
  • `JSON.parse(JSON.stringify(car))` is a lossy and inefficient way to clone objects. See [answers here](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript). – T.J. Crowder Nov 10 '20 at 13:21
  • Are you trying to add a car to one of the arrays in the array of arrays, or add a new blank array to the array of arrays, or add a new non-blank array to the array of arrays? – T.J. Crowder Nov 10 '20 at 13:23
  • what's the purpose of doing `JSON.parse(JSON.stringify(car))`? are you trying to clone the objects? also, the two examples aren't equivalent. the first is just adding a car to the end of the list but the second is wrapping it in an extra set of square brackets? presumably you've added `as ICar[];` to circumvent a type error but if you fix that type error, it should just work – Tom Finney Nov 10 '20 at 13:23
  • I basically want an array and each element in the array can be ICar[] in this case i am adding a single car – MicroMan Nov 10 '20 at 13:25

1 Answers1

1

Not sure why you use JSON.stringify. In your example

setCarList(initialList => [[...initialList],cars]);

should be actually

setCarList(initialList => [...initialList,cars]);

You nest it more times than necessary IMO. I don't know what is your requirement for that state, but if you need more ref-like state management (e.g. adding a car to your lowest-level array) consider using https://github.com/immerjs/use-immer

I also think you got your typing wrong, as [ICar[]] is actually an array with exactly one element - this causes TS errors while adding more elements to it. My guess is that you wanted ICar[][]

What's more, you may not want to initialize state with an empty array "inside", usually initial state is an empty array:

const [carList, setCarList] = React.useState<ICar[][]>([]);
Emzaw
  • 618
  • 6
  • 11
  • Thanks for your comment i tried this and i get the exception Argument of type '(initialList: [ICar[]]) => [ICar[], ICar[]]' is not assignable to parameter of type 'SetStateAction<[ICar[]]>'. – MicroMan Nov 10 '20 at 13:31
  • I think your typing is wrong then - you probably want actually ICar[][] type, not [ICar[]], which is actually always an array of one element – Emzaw Nov 10 '20 at 13:35
  • Check that sandbox if that's what you need: https://codesandbox.io/s/priceless-blackburn-8k2ty?file=/src/App.tsx – Emzaw Nov 10 '20 at 13:42
  • Thanks you very much! – MicroMan Nov 10 '20 at 14:21