Home > Mobile >  React - How to pass another component into generic component?
React - How to pass another component into generic component?

Time:01-07

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>
)
  • Related