Generic type arguments in JSX elements with withStyles

后端 未结 4 1797
别跟我提以往
别跟我提以往 2021-01-13 12:05

In React with material-ui I am trying to create a JSX component that accepts generic parameters and also uses the withStyles HOC to inject my styles.

Th

4条回答
  •  花落未央
    2021-01-13 12:29

    The more I think about the question, the more I like Frank Li's approach. I'd make two modifications: (1) introduce an extra SFC to avoid a cast, and (2) grab the outer props type from the wrapped component C instead of hard-coding it. (If we hard-coded Props, TypeScript would at least check that it is compatible with this.C, but we are at risk of requiring props that this.C doesn't actually require or failing to accept optional props that this.C actually accepts.) It's jaw-dropping that referencing a property type from a type argument in the extends clause works, but it seems to!

    class WrappedBaseFormCard extends React.Component<
      // Or `PropsOf["C"]>` from @material-ui/core if you don't mind the dependency.
      WrappedBaseFormCard["C"] extends React.ComponentType ? P : never,
      {}> {
      private readonly C = withStyles(styles)(
        // JSX.LibraryManagedAttributes handles defaultProps, etc.  If you don't
        // need that, you can use `BaseFormCard["props"]` or hard-code the props type.
        (props: JSX.LibraryManagedAttributes["props"]>) =>
           {...props} />);
      render() {
        return ;
      }
    }
    

    I think any complaints about runtime overhead of this approach are probably nonsense in the context of a whole React application; I'll believe them when someone presents data supporting them.

    Note that Lukas Zech's approach using an SFC is very different: every time the props to the outer SFC change and it is called again, withStyles is called again, generating a wrapper that looks to React like a whole new component type, so React throws away the old wrapper instance and a new inner BaseFormCard component gets created. This would have undesirable behavior (resetting state), not to mention greater runtime overhead. (I haven't actually tested this, so let me know if I'm missing something.)

提交回复
热议问题