1

I want to create a, b, div or another element based on as={""} prop in my function.

I am checking as and then use if guards to create element one-by-one. But is there any way to create html element based on as component?

I want to be able to create b, a, h4 h3 or any element without if's

I've found similar question but it uses styled components. Is it possible to do it without it?

Currently im doing this:

import * as React from 'react'

interface Props {
  children: (React.ReactChild | React.ReactNode) | (React.ReactChild[] | React.ReactNode[])
  onClick?: (e) => void
  as?: string
}

const DynElement: React.FunctionComponent<Props> = props => {
  const { as , children } = props

  return (
  <>
    {as === 'div' && <div {...props_rest}>
      {children}
    </div>}
    {as === 'b' && <b {...props_rest}>
      {children}
    </b>}
    </>
  )
}

export default DynElement

and usage is:

<DynElement as="b" onClick={...}>...</DynElement>

Using TypeScript + React.

1 Answer 1

2

Capture the as prop in an uppercase variable and use that as a JSX component:

const { as: Cmp = ‘div’, ...rest } = props;

return (
  <Cmp {...rest} />
);

No need to even pass children explicitly. It will be passed along with the ‘rest’ props.

Sign up to request clarification or add additional context in comments.

6 Comments

This gave me errors on TypeScript. Perhaps will work for JSX but on TSX I get: Type '{ children: string | number | boolean | {} | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 55 more ... | (ReactNode[] & ReactPortal); ... 8 more ...; as?: string; }' has no properties in common with type 'IntrinsicAttributes'.ts(2559)
And, If I give as: any instead of string, this time it throws an error: Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Ah no! I forgot to declare as on source :) Sorry. This is correct. I didn't know we could do like this. Thanks for the lesson.
Are you using this component without passing the “as” prop? If so you’d need to have it default to a div (or whatever). I’ll update my answer to provide a div fallback.
Updated. Now defaults to div if the prop isn’t provided.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.