Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React functional component static property

I had a class component with another class component as his static property. Now I switched to a function component and I don't know how to keep the static property.

class Panel extends React.Component<Props> {
  public static Fieldset = PanelFieldset;
}

class PanelFieldset extends React.Component<Props> {
  ...
}

class App extends React.Component<Props> {
  public render() {
    return (
      <Panel>
        <Panel.Fieldset>
          ...
        </Panel.Fieldset>
      </Panel>
    )
  }
}

Now, switching to function component:

const Panel: React.FunctionComponent<Props> = (props) => {
  Panel.Fieldset = PanelFieldset;
}

but I get the error: Property 'Fieldset' does not exist on type 'FunctionComponent'.ts(2339)

Any help?

like image 514
Simone Conti Avatar asked Aug 29 '19 14:08

Simone Conti


3 Answers

With implicit typing (Best Solution)

The following shows an apporach where you don't have to type your static properties explicitly. I personally prefer this over any other solution, since it is the shortest and most clean way.

const PanelComponent: React.FC<Props> = (props) => {
 ...
}

export const Panel = Object.assign(PanelComponent, { PanelFieldset })

With explicit typing (Previous Solution)

If you want to type your static properties explicitly, extending @Andrew's answer, using typeof PanelFieldset should be more convenient to type your component.

type IPanel<P> = React.FunctionComponent<P> & {
  Fieldset: typeof PanelFieldset; // add this
}

const Panel: IPanel<Props> = (props) => {
}

Panel.Fieldset = PanelFieldset;

Source: https://github.com/react-bootstrap/react-bootstrap/blob/master/types/components/Dropdown.d.ts

like image 104
oemera Avatar answered Oct 02 '22 07:10

oemera


For static properties on a function you declare them on the function itself i.e.

function Panel() {
}
// static props
Panel.Fieldset = PanelFieldset

A similar approach can be seen for setting propTypes on a component. I assume in TS that would look like:

Panel.Fieldset: React.Component<Props> = PanelFieldset
like image 39
James Avatar answered Oct 02 '22 06:10

James


React.FunctionComponent is scoped purely within the key props, which you discovered does not work when you want to add a property that is not in the props key. In order to properly type it, you need to make your own type and extend it.

After that, assign it outside of the function

type IPanel<P> = React.FunctionComponent<P> & {
  Fieldset: any //whatever type it actually is
}

const Panel: IPanel<Props> = (props) => {
}

Panel.Fieldset = PanelFieldset;
like image 10
Andrew Avatar answered Oct 02 '22 07:10

Andrew