0

I have a simple useState function that looks like this:

const [value, setValue] = useState<values[]>([]);

Theoretically, this will mean that the state of value defaults to an empty array.

I then have a function that I've defined like this:

  function handleSelectValue(id: string) {
      let fakeArray:Array<values> = [...Value, DefinedArray.find(x => x.id)]
      setValue(fakeArray);
  }

I also tried:

  function handleSelectValue(id: string) {
      setValue([...Value, DefinedArray.find(x => x.id)]);
  }

I would think that this code should work, however, I get an error that says

Type 'Value | Undefined' is not assignable to type 'Value'. Type 'Undefined' is not assignable to type 'Value'.

I'm not sure where, exactly, the undefinedness is coming from. It seems to me that my default value of "value" is defined as an empty array of value. (Value is defined elsewhere, to be clear, with a Guid, a name, and a few other descriptor fields).

What is wrong with this code here? I know stateful arrays can be a bit wonky, but this seems pretty straightforward to me.

phroureo
  • 377
  • 3
  • 16

2 Answers2

2

find() returns undefined if it can't find anything.

undefined is not compatible with your typing. So you should only append it here is something to append:

function handleSelectValue(id: string) {
      const findResult = DefinedArray.find(x => x.id);
      if (findResult) {
            setValue([...Value, ...findResult ]);
      }
  }

Or you could spread an empty array as fallback, if that's more readble:

setValue([ ...Value, ...(DefinedArray.find(x => x.id) || []) ]);
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • 1
    Thanks! That makes a lot of sense -- I was confused because it was returning the error on `...Value` but this has fixed it :) – phroureo Mar 13 '23 at 15:21
  • 1
    Yeah -- you can't accept an answer for 10 minutes after posting, though :) – phroureo Mar 13 '23 at 15:47
  • One more question: When I do `setValue([findResult])`, it is not setting the `Value` state -- I have run `console.log` before and after running `setValue` and in both cases it is returning an array with length 0. Any idea what might be causing that? or should I make a separate question? – phroureo Mar 13 '23 at 16:06
  • You'll need to spread it I guess: `setValue([ ...findResult ])`. But keep in mind that [`console.log()` does not show the changed value since `setValue` is async](https://stackoverflow.com/questions/54713510/console-log-after-setstate-doesnt-return-the-updated-state). – 0stone0 Mar 13 '23 at 16:09
1

If you are sure that the item exists you can do either of these:

function handleSelectValue(id: string) {
  setValue([...Value, DefinedArray.find((x) => x.id)!]);
}

or

function handleSelectValue(id: string) {
  const item = DefinedArray.find((x) => x.id)
  if (!item) throw new Error('this will never happen')
  setValue([...Value, item]);
}
Konrad
  • 21,590
  • 4
  • 28
  • 64