Next.js Image component error src missing though I am providing the src prop
Asked Answered
L

3

8

I am providing the src prop to the UserCard but then also I am getting the error below.

Error

Unhandled Runtime Error
Error: Image is missing required "src" property. Make sure you pass "src" in props to the `next/image` component. Received: {"width":50,"height":50}

The Code in different Files is below

In UserCard.js


import Avatar from './Avatar';
import Link from 'next/link';

export default function UserCard({ user, border, onClick }) {
    function handleCloseAll() {
        if (onClick) onClick();
    }
    return (
        <div
            className={`d-flex p-2 align-items-center justify-content-between w-100 ${border}`}>
            <div onClick={handleCloseAll}>
                <Link href={`/profile/${user._id}`}>
                    <a className='d-flex align-items-center text-decoration-none'>
                        <Avatar.Big src={user.avatar} />
                        <div className='ml-1' style={{ transform: 'translateY(-2px)' }}>
                            <span className='d-block'>{user.username}</span>
                            <span
                                style={{
                                    opacity: 0.7
                                }}>
                                {user.fullname}
                            </span>
                        </div>
                    </a>
                </Link>
            </div>
        </div>
    );
}

in Avatar/Big.js

import Image from 'next/image';
import { useSelector } from 'react-redux';
import styles from '../../../styles/avatar.module.css';
export default function Big({ src }) {
    const { darkMode } = useSelector(state => state);
    return (
        <div
            style={{
                filter: darkMode ? 'invert(1) hue-rotate(180deg)' : 'invert(0)'
            }}>
            <Image
                className={styles.avatar}
                width={50}
                height={50}
                src={src}
                alt='Avatar'
            />
        </div>
    );
}

in Avatar/index.js

import Super from './Super';
import Big from './Big';
import Medium from './Medium';
import Small from './Small';
const Avatar = {
    Super: Super,
    Big: Big,
    Medium: Medium,
    Small: Small
};

export default Avatar;

Effort

If I am using the native <img /> it is working as expected


import Avatar from './Avatar';
import Link from 'next/link';

export default function UserCard({ user, border, onClick }) {
    function handleCloseAll() {
        if (onClick) onClick();
    }
    return (
        <div
            className={`d-flex p-2 align-items-center justify-content-between w-100 ${border}`}>
            <div onClick={handleCloseAll}>
                <Link href={`/profile/${user._id}`}>
                    <a className='d-flex align-items-center text-decoration-none'>
                        <img src={user.avatar} />
                        <div className='ml-1' style={{ transform: 'translateY(-2px)' }}>
                            <span className='d-block'>{user.username}</span>
                            <span
                                style={{
                                    opacity: 0.7
                                }}>
                                {user.fullname}
                            </span>
                        </div>
                    </a>
                </Link>
            </div>
        </div>
    );
}

More Details

I am using Nextjs version 11.0.1

Github Repository Link for further insights :- https://github.com/KUSHAD/dogeshot

Linebreeding answered 26/7, 2021 at 4:26 Comment(0)
P
4

In Big.js try

{ src && (
    <Image 
        className={styles.avatar}
        width={50}
        height={50}
        src={src}
        alt='Avatar'
    />
)}

This only outputs the image if src has a value.

Pederast answered 26/7, 2021 at 4:41 Comment(1)
You can only mark one as the accepted answer. If you click it again on another answer it removes it from the other. You have to decide which is your preferred answer.Pederast
Z
3

It is not how the error should be handled. If image src does not exist you should at least show a default value. When you get images from API calls, sometimes images might be corrupted or link does not exist any more.

Next.js Image component documentation does not mention but the Image component has onError prop. In your component

export default function Big(props) {
  const { src } = props;
 // initially use the passed url as imgSrc
  const [imgSrc, setImgSrc] = useState(src);
  const { darkMode } = useSelector((state) => state);
  
  // If Image component throws an error, set default 
  const handleOnError = () => {
    setImgSrc("/static/yourImage.jpg");
  };
  return (
    <div
      style={{
        filter: darkMode ? "invert(1) hue-rotate(180deg)" : "invert(0)",
      }}
    >
      <Image
        className={styles.avatar}
        width={50}
        height={50}
        src={imgSrc}
        alt="Avatar"
        // if src does not exist this function will be triggered
        onError={handleOnError}
      />
    </div>
  );
}
Zohar answered 19/2, 2022 at 19:24 Comment(0)
E
1

in Avatar/Big.js you should use initial value for src. in first render the value is null add this code:

import Image from 'next/image';
import {useState,useEffect} from 'react';
import { useSelector } from 'react-redux';
import styles from '../../../styles/avatar.module.css';
export default function Big({ src }) {
const [image,setImage] = useState("/defaultImage")
useEffect(()=>{
if(src){
setImage(src)
}
},[src])
    const { darkMode } = useSelector(state => state);
    return (
        <div
            style={{
                filter: darkMode ? 'invert(1) hue-rotate(180deg)' : 'invert(0)'
            }}>
            <Image
                className={styles.avatar}
                width={50}
                height={50}
                src={image}
                alt='Avatar'
            />
        </div>
    );
}
Electromagnetism answered 26/7, 2021 at 4:47 Comment(1)
This also works as expected but I will go with the first answer as it has done this quite concisely . But anyways thanksLinebreeding

© 2022 - 2024 — McMap. All rights reserved.