I tried to create a reusable swiper component with Next.js 13 (App Router) v13.4.12 and also use TypeScript. I get an error when I try to "consume" data from the component props, which is a custom function render for the parent.
First I create the interface IItem
& ICarousell
like this also use generic for reusable
import { ReactNode } from "react";
export interface IItem {
[key: string]: undefined
}
export interface ICarousell<T> {
items: Array<T | IItem>,
children?: ReactNode,
customRender?(el: IItem | T): T | ReactNode
}
Then I created the reusable Swiper component like this, using the Interface that I created before.
"use client"
import { Swiper, SwiperSlide } from "swiper/react"
import { ICarousell } from "./Carousell.types";
import 'swiper/css';
export default function Carousell<T> ({ children, items, customRender, ...props }: ICarousell<T>) {
return (
<Swiper
{...props}
>
{items.map((item, idx) => (
<SwiperSlide key={idx}>
<>
{customRender ? customRender(item) : item }
</>
</SwiperSlide>
))}
{children}
</Swiper>
)
}
After that, I tried to use the Carousell
component on the Home page, but I got an error similar to the image I attached below.
import { Carousell } from "@/core/components";
export default function Home() {
return (
<main>
<Carousell
items={[
1,
]}
customRender={(element) => (
<div>{element}</div>
)}
/>
</main>
)
}
And I tried to edit my generic just for testing like this
export interface ICarousell<T> {
items: Array<T | IItem>,
children?: ReactNode,
customRender?(el: any): ReactNode // Use "any" for the parameter type
}
I tried not to change the custom render type with any
, and I tried using a React fragment tag, it worked.
<Carousell
items={[
1,
]}
customRender={(element) => (
<>{element}</>
)}
/>
but if I tried again to add the div
inside the fragment
tag like this, it wouldn’t work again.
<Carousell
items={[
1,
]}
customRender={(element) => (
<>
<div>{element}</div>
</>
)}
/>
I’m not sure, but I think the problem is the parameter type. I don’t know how to deal with it. Hopefully you guys can help me. Thanks in advance. Any feedback will be appreciated.
2
Answers
Since you’re using arrow function on customRender
You could modify ICarousel interface like this
Reference: https://www.typescriptlang.org/docs/handbook/interfaces.html#function-types
In
ICarousell
, thecustomRender
is expected to return eitherT
orReactNode
. But in usage you are returning a JSX element<div>{element}</div>
which is of typeReactNode
. I think this is conflicting with the typeT
you inferred – in this case it is a number (as the items array containing numbers).I would adjust the type definitions to make sure the
customRender
always returns aReactNode
since you are rendering result in JSX.ICarousell interface
You dont need extra tags around the
customRender
😉Usage