I have a function, which takes two params: a react ponent, and a string. I am trying to give them correct typings, however, am confused as to why the following wont work...
The problem is with the typing with GivenComponent in the Function. By giving the param that specific typing of Component<>, the return of the GivenComponent (within the < Query />) errors stating the following:
JSX element type 'GivenComponent' does not have any construct or call signatures. [2604]
However, how would you type that correctly? That param is a React Component, could be both a functional or a class ponent. As seen in the second part of code, the param isn't given as < MyComponent />, it is given as MyComponent - so not the "rendered" jsx? maybe that changes things
Function:
Basically takes a ponent and returns it with a higher order ponent wrapper around it
import React, { Component } from "react";
const withQueryData: Function = (
GivenComponent: Component<{ data: {} }, any>,
query: string
) => () => (
<Query query={gql(query)}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error! {error.message}</p>;
return <GivenComponent data={data} />;
}}
</Query>
);
export default withQueryData;
React Component:
example of how the function above is called with params
class MyComponent extends Component<...removed...> {
render() {
return (
<div>...</div>
);
}
}
const MyComponentQuery = `query goes here...`;
const MyComponentWithData = withQueryData(
MyComponent,
MyComponentQuery
);
export default MyComponentWithData;
I have a function, which takes two params: a react ponent, and a string. I am trying to give them correct typings, however, am confused as to why the following wont work...
The problem is with the typing with GivenComponent in the Function. By giving the param that specific typing of Component<>, the return of the GivenComponent (within the < Query />) errors stating the following:
JSX element type 'GivenComponent' does not have any construct or call signatures. [2604]
However, how would you type that correctly? That param is a React Component, could be both a functional or a class ponent. As seen in the second part of code, the param isn't given as < MyComponent />, it is given as MyComponent - so not the "rendered" jsx? maybe that changes things
Function:
Basically takes a ponent and returns it with a higher order ponent wrapper around it
import React, { Component } from "react";
const withQueryData: Function = (
GivenComponent: Component<{ data: {} }, any>,
query: string
) => () => (
<Query query={gql(query)}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error! {error.message}</p>;
return <GivenComponent data={data} />;
}}
</Query>
);
export default withQueryData;
React Component:
example of how the function above is called with params
class MyComponent extends Component<...removed...> {
render() {
return (
<div>...</div>
);
}
}
const MyComponentQuery = `query goes here...`;
const MyComponentWithData = withQueryData(
MyComponent,
MyComponentQuery
);
export default MyComponentWithData;
Share
Improve this question
edited Mar 20, 2019 at 15:45
user10741122
asked Mar 20, 2019 at 15:42
user10741122user10741122
8911 gold badge16 silver badges29 bronze badges
5
-
Try to use
React.ComponentClass | React.FunctionComponent
instead ofReact.Component
– Limbo Commented Mar 20, 2019 at 15:44 - @LevitatorImbalance but the param can be either class ponent or functional. I thought ComponentClass indicates it is a Class Component? – user10741122 Commented Mar 20, 2019 at 15:47
- Just reviewed a question and edited my ment) – Limbo Commented Mar 20, 2019 at 15:49
-
1
Or use
ComponentType
, also don't use: Function
that disables inference forwithQueryData
– Titian Cernicova-Dragomir Commented Mar 20, 2019 at 15:53 - Also won't you want to forward some props from the wrapper ponent to the wrapped ponent ? Your current versions does nto allow any extra props – Titian Cernicova-Dragomir Commented Mar 20, 2019 at 15:54
2 Answers
Reset to default 4Transforming my ment into an answer.
There are two typings for declared react ponents:
React.ComponentClass
- a typing for react ponent that is declared as class:
class SomeComponent extends React.Component {...} // this is React.ComponentClass
React.FunctionComponent
is a typing for function ponent (CO to the rescue! :D)
const MyFunctionComponent: React.FunctionComponent = props => "something"
So, if your ponent is one of ComponentClass
or FunctionComponent
, you can use Union Type and tell the TypeScript about it in this way:
const SomeUnionType: React.ComponentClass | React.FunctionComponent
Thats it! Hope, that helps :)
You need to use ComponentType
to represent a ponent type (functional or class, defined in react definitions as type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;
).
Also you might want to allow the HOC to forward properties from the wrapped ponent.
Also remove the Function
annotation from withQueryData
as that will remove all type safety from withQueryData
.
import { Component, ComponentType } from "react";
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
const withQueryData = <P extends { data: {} }>(
GivenComponent: ComponentType<P>,
query: string
) => (p: Omit<P, 'data'>) => (
<Query query={gql(query)}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error! {error.message}</p>;
return <GivenComponent data={data} {...p as any} />;
}}
</Query>
);
class MyComponent extends Component<{ data: {}, otherProp: string }> {
render() {
return (
<div>...</div>
);
}
}
const MyComponentQuery = `query goes here...`;
const MyComponentWithData = withQueryData(
MyComponent,
MyComponentQuery
);
export default MyComponentWithData;
let o = () => <MyComponentWithData otherProp="" ></MyComponentWithData> // otherProp required, data provided bu the HOC
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745090884a4610688.html
评论列表(0条)