I practiced creating a dropdown menu with
- hardcoded array before trying to create a
- dropdown menu with an array retrieved with useSWR.
I used this for the first practice: https://codesandbox.io/s/76k0ft?file=/demo.tsx:1819-2045
Instead of using the hardcoded names
variable,I saved a fetched array as shown:
const { data, error } = useSWR(
"https://api.github.com/repos/vercel/swr",
fetcher
);
if (error) return <h1>"An error has occurred."</h1>;
if (!data) return <h1>"Loading..."</h1>;
const arr = data.topics;
I rendered it as shown:
{arr.map((tag,id)=> (
<MenuItem
key={id}
value={tag}
>
{tag}
</MenuItem>
))}
To which I was given red underlines for the parameter that says the following when cursor is placed over the tag
and id
parameters.
Parameter 'tag' implicitly has an 'any' type.ts(7006)
I clicked on the suggested Quick fixes and now the MenuItem and its props are underlined.
After Quick fixes it looks like this
{arr.map((tag: {} | null | undefined,id: React.Key | null | undefined)=> (
<MenuItem
key={id}
value={tag}
>
{tag}
</MenuItem>
))}
The message I get from hovering over the red underlines is
No overload matches this call. Overload 1 of 3, '(props: { href: string; } & { autoFocus?: boolean | undefined; classes?: Partial | undefined; dense?: boolean | undefined; disabled?: boolean | undefined; disableGutters?: boolean | undefined; divider?: boolean | undefined; selected?: boolean | undefined; sx?: SxProps<...> | undefined; } & Omit<...> & CommonProps & Omit<...>): Element', gave the following error. Type '{ children: {} | null | undefined; key: Key | null | undefined; value: {} | null | undefined; }' is not assignable to type 'IntrinsicAttributes & { href: string; } & { autoFocus?: boolean | undefined; classes?: Partial | undefined; dense?: boolean | undefined; ... 4 more ...; sx?: SxProps<...> | undefined; } & Omit<...> & CommonProps & Omit<...>'. Property 'value' does not exist on type 'IntrinsicAttributes & { href: string; } & { autoFocus?: boolean | undefined; classes?: Partial | undefined; dense?: boolean | undefined; ... 4 more ...; sx?: SxProps<...> | undefined; } & Omit<...> & CommonProps & Omit<...>'. Overload 2 of 3, '(props: { component: ElementType; } & { autoFocus?: boolean | undefined; classes?: Partial | undefined; dense?: boolean | undefined; ... 4 more ...; sx?: SxProps<...> | undefined; } & Omit<...> & CommonProps & Omit<...>): Element', gave the following error. Property 'component' is missing in type '{ children: {} | null | undefined; key: Key | null | undefined; value: {} | null | undefined; }' but required in type '{ component: ElementType; }'. Overload 3 of 3, '(props: DefaultComponentProps<ExtendButtonBaseTypeMap<MenuItemTypeMap<{}, "li">>>): Element', gave the following error. Type '{} | null | undefined' is not assignable to type 'string | number | readonly string[] | undefined'. Type 'null' is not assignable to type 'string | number | readonly string[] | undefined'.ts(2769) OverridableComponent.d.ts(17, 7): 'component' is declared here. index.d.ts(2246, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & { autoFocus?: boolean | undefined; classes?: Partial | undefined; dense?: boolean | undefined; ... 4 more ...; sx?: SxProps<...> | undefined; } & Omit<...> & CommonProps & Omit<...>'
What is the difference between mapping through a hardcoded array and an array fetched using useSRW? There were no red underline in the first example.
The code works, but I am trying to understand how Typescript works. I also get this warning message in the console:
react-dom.development.js:67 Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
CodePudding user response:
The array listed in the sandbox is an array of string
. Therefore mapping the individual element should give a string. Hope this helps.
{arr.map((tag:string,id:number)=> (
<MenuItem
key={id}
value={tag}
>
{tag}
</MenuItem>
))}