Typed React Function Component Template using Velocity Template Language

Viewed 39

I am using Webstorm as my IDE. It allows me to highlight some JSX and extract a component as a function component. The code powering this feature is in VTL which I am not familiar with. When I extract a component such as this:

<button color="primary" onClick={reset} onBlur={handleBlur}>
  Cancel
</button>

VTL should create a function component with this signature:

interface NewComponentProps {
  onClick: () => void;
  onBlur: () => void;
}   
 
const NewComponent: React.FC<NewComponentProps> = ({ onClick, onBlur }) => {
      return (
        <button color="primary" onClick={onClick} onBlur={onBlur}>
          Cancel
        </button>
      );
    };

However, the VTL I have written is returning a function component with a signature of:

interface NewComponentProps {
  onClick: () => void;
  onBlur: () => void;
}

 const NewComponent: React.FC<NewComponentProps> = ({ onClick }) => {
      return (
        <button color="primary" onClick={onClick} onBlur={onBlur}>
          Cancel
        </button>
      );
    };

Which is not quite right. Notice the destructuring of the props only shows the first prop, and not the rest.

Here is the VTL template I wrote that is wrong:

    #if($PROP_TYPES)
interface ${NAME}Props 
    $PROP_TYPES
#end

#if($PROP_TYPES) #set($prop = $PROP_TYPES.substring(0, $PROP_TYPES.indexOf(":")).concat("}"))#end

#set( $BODY_NO_PROPS = $COMPONENT_BODY.replace("props.", "") )

const $NAME: React.FC#if($PROP_TYPES)<${NAME}Props>#end = (#if($PROP_TYPES) $prop#end) => {
  return $BODY_NO_PROPS
}

#if($DEFAULT_PROPS)
  $!{NAME}.defaultProps = $DEFAULT_PROPS
#end

I believe my issue stems from this line of VTL #if($PROP_TYPES) #set($prop = $PROP_TYPES.substring(0, $PROP_TYPES.indexOf(":")).concat("}"))#end

I think the data structure is a map, and my code is not looping through the map to get all the keys of the map to display all the props.

Predefined variables will take the following values:
${NAME} - component name

${COMPONENT_BODY} - component body

${PROP_TYPES} - props type definition

How can I rewrite this template to take the form I want it too?

1 Answers

You can get rid of props: <type> with

#if($PROP_TYPES) #set($prop = $PROP_TYPES.substring(0, $PROP_TYPES.indexOf(":")).concat("}"))#end

const $NAME: React.FC<#if($PROP_TYPES) $PROP_TYPES#end> = (#if($PROP_TYPES) $prop#end) => {
  return $COMPONENT_BODY
}

Velocity supports Java String methods, you can try using them to parse the $PROP_TYPES and $COMPONENT_BODY strings accordingly. You can use regexp, for example ($PROP_TYPES.replaceAll($regex, $replacement))

Related