My component is not rendering due to type mismatch (StaticImageData =/= String)

84 views Asked by At

Nextjs and React beginner here.

I made an <ImageSlider /> component for my Nextjs website, but it will not render on my home page due to a type mismatch. Nextjs is expecting StaticImageData, but is instead receiving a string URL.

Important to note that I made the <ImageSlider /> component following a tutorial using create-vite/react.

Here is the error I'm receiving when trying to call the <ImageSliderApp /> in my home page in the page.tsx file:

'ImageSliderApp' cannot be used as a JSX component.
 Its type '() => void' is not a valid JSX element type.
   Type '() => void' is not assignable to type '(props: any, deprecatedLegacyContext?: any) => ReactNode'.
     Type 'void' is not assignable to type 'ReactNode'.ts(2786)

The <ImageSliderApp /> component is referencing the actual <ImageSlider /> in my image-sliderapp.tsx file, which is being imported into my page.tsx file:

import Image, { StaticImageData } from "next/image";
import React, { Component } from "react";
import { ImageSlider } from "./image-slider";
import WaefMvp from "../../imgsandbox/components/public/waef-mvp.png";
import WaefLbte from "../../imgsandbox/components/public/waef-lbte.png";
import WaefDnb from "../../imgsandbox/components/public/waef-dnb.png";

const imageArray = [
  { src: WaefMvp, alt: "MVP", },
  { src: WaefLbte, alt: "Lbte", },
  { src: WaefDnb, alt: "Dnb" },
];

export default function ImageSliderApp() {
  return;
  <div>
    <ImageSlider images={imageArray} />
  </div>;
}

However, I receive the following type mismatch error when trying to pass the images={imageArray} prop in the <ImageSlider /> component:

Type '{ url: string; alt: string; }[]' is not assignable to type '{ url: StaticImageData; alt: string; }[]'.
  Type '{ url: string; alt: string; }' is not assignable to type '{ url: StaticImageData; alt: string; }'.
    Types of property 'url' are incompatible.
      Type 'string' is not assignable to type 'StaticImageData'.ts(2322)
image-slider.tsx(7, 3): The expected type comes from property 'images' which is declared here on type 'IntrinsicAttributes & ImageSliderProps'

Finally, here is the code for the actual component:

import Image, { StaticImageData } from "next/image";
import React, { useState } from "react";
import { ChevronLeft, ChevronRight, Dot, Asterisk } from "lucide-react";
import "./image-slider.css";

type ImageSliderProps = {
  images: {
    url: StaticImageData;
    alt: string;
  }[];
};

export function ImageSlider({ images }: ImageSliderProps) {
  const [imageIndex, setImageIndex] = useState(0);
  function showPrevImage() {
    setImageIndex((index) => {
      if (index === 0) return images.length - 1;
      return index - 1;
    });
  }
  function showNextImage() {
    setImageIndex((index) => {
      if (index === images.length - 1) return 0;
      return index + 1;
    });
  }
  return (
    <section
      aria-label="Image Carousel"
      style={{ width: "100%", height: "100%", position: "relative" }}
    >
      <div
        style={{
          width: "100%",
          height: "100%",
          display: "flex",
          overflow: "hidden",
        }}
      >
        {images.map(({ url, alt }, index) => (
          <Image
            key={index}
            src={url}
            alt={alt}
            aria-hidden={imageIndex !== index}
            className="img-slider-img"
            style={{ translate: `${-100 * imageIndex}%` }}
          />
        ))}
      </div>

      <button
        onClick={showPrevImage}
        className="img-slider-btn"
        style={{ left: 0 }}
        aria-label="View Previous Image"
      >
        <ChevronLeft aria-hidden />
      </button>
      <button
        onClick={showNextImage}
        className="img-slider-btn"
        style={{ right: 0 }}
        aria-label="View Next Image"
      >
        <ChevronRight aria-hidden />
      </button>

      <div
        style={{
          position: "fixed",
          bottom: ".5rem",
          left: "50%",
          translate: "-50%",
          display: "flex",
          gap: ".25rem",
        }}
      >
        {images.map((_, index) => (
          <button
            key={index}
            className="img-slider-dot-btn"
            onClick={() => setImageIndex(index)}
            aria-label={`View Image ${index}`}
          >
            {index === imageIndex ? (
              <Asterisk aria-hidden />
            ) : (
              <Dot aria-hidden />
            )}
          </button>
        ))}
      </div>
    </section>
  );
}

Ultimately, Nextjs is is expecting StaticImageData, but is instead receiving a string URL.

I tried the following:

  • Ensure my image file imports and file paths are correct
  • Ensure correct imports of components
  • Ensure the type ImageSliderProps is receiving the images as StaticImageData

What can I try next?

1

There are 1 answers

0
Jason Ming On

The main error is "Type 'void' is not assignable to type 'ReactNode'", because you returned void in ImageSliderApp component.

return;

Please update it as following.

export default function ImageSliderApp() {
  return (
      <div>
          <ImageSlider images={imageArray} />
      </div>
  );
}