I'm trying to use React Hooks in my HOC to pass an event to parent that says when this component is on Viewport, to lazy load this component data using React Intersection Observer, but I'm struggling with the following error: Type '(props: IStockProps) => JSX.Element | JSX.Element[]' is not assignable to type 'FC<IStockProps>'.
I started recently with Typescript and I'm still getting on how to read these errors and sometimes can be a bit confusing. This are my code
HOC
import React, { useEffect, ComponentType, Component } from "react";
import { useInView } from "react-intersection-observer";
interface IHocProps {
[key: string]: any;
}
export const LazyLoader = (WrappedComponent: ComponentType<IHocProps>) =>
function Comp(props: IHocProps) {
const { onEnterView } = props;
const [ref, inView] = useInView({
triggerOnce: true,
});
useEffect(() => {
inView && onEnterView();
}, [inView]);
return <WrappedComponent ref={ref} {...props} />;
};
Component:
import React from "react";
import { Skeleton, Space } from "antd";
interface IStockProps {
isLoading: boolean;
stockSituation: object;
}
export const StockSituation: React.FC<IStockProps> = (props: IStockProps) => {
const { isLoading, stockSituation } = props;
const renderSkeleton = (
<>
<Skeleton paragraph={{ rows: 2 }} active={true} />
<Space
style={{ justifyContent: "center" }}
direction="horizontal"
align="center"
size="large"
>
<Skeleton.Avatar size={200} active={true} />
<Skeleton.Avatar size={200} active={true} />
<Skeleton.Avatar size={200} active={true} />
<Skeleton.Avatar size={200} active={true} />
</Space>
</>
);
return isLoading
? renderSkeleton
: Object.keys(stockSituation).map((stock) => (
<p>{stockSituation[stock as keyof IStockProps["stockSituation"]]}</p>
));
};
Dashboard
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "@store";
import {getStock, IStock} from "@store/dashboard/dashboard";
import { Grid, Row, Col } from "react-flexbox-grid";
import {LazyLoader} from "@components";
const stock: IStock = useSelector(
({ dashboard: { stock } }: RootState) => stock
);
const loadInfo = () => {
console.log("info");
dispatch(getStock());
};
const LazyStockSituation = LazyLoader(StockSituation);
return (
<>
<Header />
<Grid>
<Row>
<Col>
<LazyStockSituation
onEnterView={loadInfo}
stockSituation={stock}
isLoading={!stock}
/>
</Panel>
</Col>
</Row>
</Grid>
</>
);
};
Edit: So, I figure out that this error was cause by the Component and not by the HOC, so I fix it, but now I'm getting new errors, pretty more scary
Argument of type 'FC<IStockProps>' is not assignable to parameter of type 'ComponentType<IHocProps>'.
Type 'FunctionComponent<IStockProps>' is not assignable to type 'FunctionComponent<IHocProps>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'PropsWithChildren<IHocProps>' is not assignable to type 'PropsWithChildren<IStockProps>'.
Type 'PropsWithChildren<IHocProps>' is missing the following properties from type 'IStockProps': isLoading, stockSituation
All this errors are about trying to pass props with interface IHocProps to the component that receive props with interface IStockProps, right? Is there a way to make my HOC receive the more generic possible types so I can use it with any other component?