Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Types of property 'src' are incompatible in nextjs/image

I am using react dropzone to upload multi-image in my simple application. For showing which type of images are drop for that I make a separate component with TypeScript. But Next.js image src is showing error like Type:

'{ src: string; alt: string; }' is not assignable to type 'IntrinsicAttributes & ImageProps'.
  Type '{ src: string; alt: string; }' is not assignable to type 'ObjectImageProps'.
    Types of property 'src' are incompatible.
      Type 'string' is not assignable to type 'StaticImport'.

RenderFiles.ts:

import { IFile } from "../../libs/types";
import { sizeInMb } from "../../libs/sizeInMb";
import { FunctionComponent } from "react";
import Image from "next/image"

const RenderFile: FunctionComponent<{
  file: IFile;
}> = ({ file: { formate, sizeInBytes, name } }) => {
  return (
    <div>
      <Image src={`/images/${formate}.png`} alt="image"/>
      <span>{name}</span>
      <span>{sizeInMb(sizeInBytes)}</span>
    </div>
  );
};

export default RenderFile;

types.ts:

export interface IFile {
  name: string;
  sizeInBytes: number;
  formate: string | number;
  id?: string;
}

What is my mistake in src props?

like image 992
Arif hossain Avatar asked Jun 27 '21 05:06

Arif hossain


People also ask

How do I allow all domains in next image?

An alternative is to use <img /> tag instead of Next JS <Image /> tag.

Can we use IMG tag in next JS?

There are two ways you can display images in Next. js, you either use the conventional <img> tag or a specialized <Image/> component that is unique to Next. The differences between these tags are quite much, but they pretty much do the same thing; which is to display images to the browser.

How do I add images to Nextjs?

Firstly import the image component in next. js and define the image path in src props in the image component. Now your image shows in the browser. In the image component, src, width, and height props are required by next.


2 Answers

The issue is next/image's Image is expecting rather complex type ImageProps as it's props:

type StringImageProps = {
  src: string
} & (
  | { width?: never; height?: never; layout: 'fill' }
  | {
      width: number | string
      height: number | string
      layout?: Exclude<LayoutValue, 'fill'>
    }
) &
  (
    | {
        placeholder?: Exclude<PlaceholderValue, 'blur'>
        blurDataURL?: never
      }
    | { placeholder: 'blur'; blurDataURL: string }
  )

type ObjectImageProps = {
  src: StaticImport
  width?: number | string
  height?: number | string
  layout?: LayoutValue
  placeholder?: PlaceholderValue
  blurDataURL?: never
}

export type ImageProps = Omit<
  JSX.IntrinsicElements['img'],
  'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' | 'style'
> & {
  loader?: ImageLoader
  quality?: number | string
  priority?: boolean
  loading?: LoadingValue
  unoptimized?: boolean
  objectFit?: ImgElementStyle['objectFit']
  objectPosition?: ImgElementStyle['objectPosition']
} & (StringImageProps | ObjectImageProps)

Since you're not importing image from local imports the only structure you're left is StringImageProps. To conform to it you have to provide one of the following props sets:

<Image src={string} layout="fill" />
// or
<Image src={string} width={number} height={number} /> // with optional `layout` prop but not of type 'fill'

both variants may be extended with optional placeholder (not of type 'blur') or required placeholder: 'blur' and blurDataURL: string.

And only after that you may provide native image's attributes as alt.

like image 175
aleksxor Avatar answered Oct 16 '22 06:10

aleksxor


Importing the type for ImageLoaderProps solved the issue for me.

Example:

import Image from 'next/image';
import type { ImageLoaderProps } from 'next/image';

const myLoader = ({ src, width, quality }: ImageLoaderProps) => {
  return `https://example.com/?${src}?w=${width}&q=${quality}`;
};

export default function AppStoreBox(props: Record<string, string>) {
  const { imageResource } = props;
  return (
        <Image
          loader={myLoader}
          src={`/${imageResource}`}
          width="20%"
          height="20%"
        />
  );
}
like image 2
EternalObserver Avatar answered Oct 16 '22 08:10

EternalObserver