<div id="app">
interface Shape {
  render(): React.JSX;
}

interface ShapeRendererProps {
  shape: Shape;
}

type ShapeProps = (width: number, height: number) => Shape;

const Circle: ShapeProps = (height: number, width: number): Shape => {
  return {
    render: () => (<div>(CIRCLE) Height: {height}, width: {width}</div>)
  }
}

const Square: ShapeProps = (height: number, width: number): Shape => {
  return {
    render: () => (<div>[SQUARE] Height: {height}, width: {width}</div>)
  }
}

const ShapeRenderer: React.FC<ShapeRendererProps> = ({ shape }) => shape && shape.render ? shape.render() : null;

const MyForm: React.FC = () => {
  const [ shape, setShape ] = React.useState(undefined);
  return (
    <div>
      <div><ShapeRenderer shape={shape}/></div>
      <div><button onClick={() => setShape(new Circle(5, 5))}>Circle</button></div>
      <div><button onClick={() => setShape(new Square(5, 5))}>Square</button></div>
    </div>
  )
}

ReactDOM.render(<MyForm/>, document.getElementById("app"));

View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js