I want to remove/separate layout from filter dropdown component as it makes generic component completely useless outside of some specific use-case
transfer-assets.tsx
<FilterDropdown
data={pensionFunds?.pension_funds}
/>
filter-dropdown.tsx
interface FilterDropdownProps {
/* eslint-disable @typescript-eslint/no-explicit-any */
data: any[] | undefined
dropdownDataLayout: JSX.Element
}
export const FilterDropdown = ({
data,
dropdownDataLayout: DropdownDataLayout,
}: FilterDropdownProps) => {
return (
<SelectField>
{data?.map((option: Record<string, any>, index: number) => (
// How to render dropdownDataLayout here ? My idea but is not working -> <DropdownDataLayout option={option} key={index} />
))}
</SelectField>
)
}
My idea is to pass prop like this, from transfer-assets.tsx
const TransferAssetsLayout = ({
option,
index,
}: TransferAssetsLayoutProps) => {
return (
...
)
}
<FilterDropdown
data={pensionFunds?.pension_funds}
dropdownDataLayout={TransferAssetsLayout}
/>
, but this is not working because I need to pass option
and key
props how to pass props options
and key
props to the filter-dropdown.tsx
component in order to render the desired layout?
CodePudding user response:
You probably want to be typing dropdownDataLayout
as React.FunctionComponent
(the function that renders a JSX element) rather than JSX.Element (the JSX node materialized by the function). You can provide a generic definition which restricts the React component passed to only those which provide a known set of props (in this case, I'm reusing TransferAssetsLayoutProps
but you may want a more generic interface that each of your layouts conforms to)
interface FilterDropdownProps {
/* eslint-disable @typescript-eslint/no-explicit-any */
data: any[] | undefined
dropdownDataLayout: React.FC<TransferAssetsLayoutProps>
}
Then you can use React.createElement to materialize it - JSX like <TransferAssetsLayout {...props} />
is just syntactic sugar for React.createElement(TransferAssetsLayout, props)
, so if you have a function component in a variable, rather than using JSX, you can just call React.createElement
directly.
return (
<SelectField>
{data?.map((option: Record<string, any>, index: number) => (
React.createElement(dropdownDataLayout, {option, key: index})
))}
</SelectField>
)