Jake Conkerton-Darby
Jake Conkerton-Darby

Reputation: 1101

How do I use a StyledComponent where React.Component is expected?

I'm trying to create a typescript React app that and have run into an issue when using styled-components. Below is a rough idea of what I'm attempting:

import React from 'react';
import styled from 'styled-components';

export type MyProps = {
  wrapper?: React.Component,
};

const DefaultWrapper = styled.div`
  background: blue;
`;

const MyComponent = ({wrapper: Wrapper = DefaultWrapper}: MyProps) => {
  return <Wrapper className='my-wrapper'>
    Some child content
  </Wrapper>;
}

export default MyComponent;

My issue comes when I try to render MyComponent within another component as it throws an error saying JSX element type 'Wrapper' does not have any construct or call signatures.

I'd like some way that I could use a styled component as either the default value or as a valid value for the wrapper prop in such a way as to not expose that I'm using styled components internally. Any help would be appreciated.

Upvotes: 0

Views: 527

Answers (1)

Matt Carlotta
Matt Carlotta

Reputation: 19762

Problem

React.Component is a React class element (not a type), instead, use the type React.ComponentType<any>. If you're working with component type constraints and expect wrapper to be certain type of component, then swap out the React.ComponentType<any> with the necessary constraint(s) -- like React.ComponentClass<any, any> for class-based components or React.FC<any> for functional components.

Solution

import * as React from "react";
import styled from "styled-components";

export type MyProps = {
  wrapper?: React.ComponentType<any>;
};

const DefaultWrapper = styled.div`
  background: blue;
`;

const MyComponent = ({ wrapper: Wrapper = DefaultWrapper }: MyProps) => {
  return <Wrapper className="my-wrapper">Some child content</Wrapper>;
};

export default MyComponent;

Working repo

Ignore the 'React' was used before it was defined. eslint warning, it's a codesandbox issue -- works fine locally:

Edit Typescript - Defaults

Upvotes: 1

Related Questions