Next.js Image component error src missing - javascript

I have the following error occurring when I attempt to use the next.js image component.
Error: Image is missing required "src" property. Make sure you pass "src" in props to the `next/image` component. Received: {}
The src value being passed in is:
https://res.cloudinary.com/mward82/images/q_auto:eco/v1616884491/1E3EDA11-D657-4FBD-8123-EFE0C5F43AC8_idzuc7/1E3EDA11-D657-4FBD-8123-EFE0C5F43AC8_idzuc7.webp
I can confirm this when I use img instead of Image.
The following is the code in question, from components/cover-image.js
import cn from "classnames";
import Link from "next/link";
import Image from "next/image";
export default function CoverImage({ title, coverImage, slug }) {
const image = (
<Image
src={coverImage?.sourceUrl}
height={coverImage?.mediaDetails.height}
width={coverImage?.mediaDetails.width}
className={cn("shadow-small", {
"hover:shadow-medium transition-shadow duration-200": slug
})}
/>
);
console.log(coverImage);
return (
<div className="sm:mx-0">
{slug ? (
<Link as={`/posts/${slug}`} href="/posts/[slug]">
<a aria-label={title}>{image}</a>
</Link>
) : (
image
)}
</div>
);
}
My next.config.js files contains the following:
module.exports = {
images: {
domains: ["res.cloudinary.com"]
}
};
You can see a forked copy of my sandbox
https://codesandbox.io/s/script-hungryvercelapp-forked-7wd9e

The problem was that my page was listing posts that don’t contain images. Modifying the code in components/cover-image.js to check for the existence of coverImage solved the problem.
The two references to image in the return section were changed to coverImage && image so that the image component rendered conditionality based on the existence of coverImage.
This is the working components/cover-image.js:
import cn from "classnames";
import Link from "next/link";
import Image from "next/image";
export default function CoverImage({ title, coverImage, slug }) {
const image = (
<Image
src={coverImage?.sourceUrl}
height={coverImage?.mediaDetails.height}
width={coverImage?.mediaDetails.width}
className={cn("shadow-small", {
"hover:shadow-medium transition-shadow duration-200": slug
})}
/>
);
console.log(coverImage);
return (
<div className="sm:mx-0">
{slug ? (
<Link as={`/posts/${slug}`} href="/posts/[slug]">
<a aria-label={title}>{coverImage && image}</a>
</Link>
) : (
coverImage && image
)}
</div>
);
}
Thanks to Yash Sangai for pushing me in the correct direction.

Related

error while go back to previous pages using breadcrumbs with reactjs and react-router-v5

I'm make a breadcrumb using reactjs and react-router v5. I'm getting error when i'm click to previous page in breadcumbs. the application becomes hang. here's my breadcrumb.
showing the recent url pages is work. But the problem is when i want to back to previous page from breadcrumbs, my apps become hang, and i'm getting this error.
And then i'm getting the weird things about url. when i'm done in the last page. when i'm hover the link in breadcrumbs , it looks same.
it's weird , because the url of dashboard is '/'.
Here's my breadcrumbs code.
import React from "react";
import { Breadcrumb } from "react-bootstrap";
import { Link, withRouter } from "react-router-dom";
const Breadcrumbs = (props) => {
const {
history,
location: {pathname}
} = props;
const pathnames = pathname.split("/").filter(x => x);
return (
<Breadcrumb aria-label="breadcrumb">
<Link onClick={() => history.push("/")}> Dashboard</Link>
{
pathnames.map((name, index) => {
const routeTo = `/${pathnames.slice(0, index + 1).join("/")}`;
const isLast = index === pathnames.length - 1;
return isLast ? (<>
<Breadcrumb.Item key={name}>{name}</Breadcrumb.Item> </>
) : (
<Link key={name} onClick={() => history.push(routeTo)}>{name}</Link>
)
})
}
</Breadcrumb>
);
};
export default withRouter(Breadcrumbs);
I want my breadcrumbs work like this.
Demo Breadcrumbs
i'm stuck. any help will be appreciated. Thank you.
The react-router-dom Link component requires a to prop with a valid string or Path object with pathname property.
Instead of
<Link onClick={() => history.push("/")}>Dashboard</Link>
...
<Link key={name} onClick={() => history.push(routeTo)}>{name}</Link>
use
<Link to="/">Dashboard</Link>
...
<Link key={name} to={routeTo}>{name}</Link>

React-Markdown Custom Component Declaration, How Can I Declare in the Renderer to Use a Custom Component?

Problem
Using React-Markdown I can fully use my custom built components. But this is with specific pre-built keywords in the markdown. Like paragraph or images. That works PERFECTLY. But the problem is that these seem to all be pre-built words/conditions like paragraphs, headers, or images.
I can't find a way to add something new key word in my markdown like "CustomComponent" to be used. That's all I need at this point ><
This works just fine for me to make the markdown's image into a custom "footer" component I made elsewhere. I know it's ridiculous but it works. But I have no idea how to make this renderer accept/create a new keyword like "emoji" or "customComponent" or "somethingSilly".
let body =
`![Fullstack React](https://dzxbosgk90qga.cloudfront.net/fit-in/504x658/n/20190131015240478_fullstack-react-cover-medium%402x.png)`;
const renderers = {
image: () => <Footer/>
};
<ReactMarkdown source={body} renderers={renderers} />;
Some past work I did:
Some documentation:
https://reposhub.com/react/miscellaneous/rexxars-react-markdown.html
https://github.com/rexxars/commonmark-react-renderer/blob/master/src/commonmark-react-renderer.js#L50
Examples:
https://codesandbox.io/s/react-markdown-with-custom-renderers-961l3?from-embed=&file=/src/App.js
But nothing indicates how I can use "CustomComponent" to indicate to inject a custom component.
Use Case / Background
I'm trying to retrieve an article from my database that is formatted like so in markdown (basically a giant string). I'm using regular react with typescript and redux-- this is the only portion of my application that needs this.
"
# Title
## Here is a subtitle
Some text
<CustomComponentIMade/>
Even more text after.
<CustomComponentIMade/>
"
I know its most likely a little late for your purposes, but I've managed to solve this issue using a custom remark component.
Essentially you'll need to use the remark-directive plugin as well as a small custom remark plugin (I got this plugin straight from the remark-directive docs)
Then in react markdown you can specify the plugins, custom renderers and custom tags for eg.
import React from 'react'
import ReactMarkdown from 'react-markdown'
import {render} from 'react-dom'
import directive from 'remark-directive'
import { MyCustomComponent } from './MyCustomComponent'
import { visit } from "unist-util-visit"
import { h } from "hastscript/html.js"
// react markdown components list
const components = {
image: () => <Footer/>,
myTag: MyCustomComponent
}
// remark plugin to add a custom tag to the AST
function htmlDirectives() {
return transform
function transform(tree) {
visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
}
function ondirective(node) {
var data = node.data || (node.data = {})
var hast = h(node.name, node.attributes)
data.hName = hast.tagname
data.hProperties = hast.properties
}
}
render(
<ReactMarkdown components={components} remarkPlugins={[directive, htmlDirectives]}>
Some markdown with a :myTag[custom directive]{title="My custom tag"}
</ReactMarkdown>,
document.body
)
So in your markdown wherever you have something like :myTag[...]{...attributes} you should render the MyCustomComponent with attributes as props.
Sorry I haven't tested the code, but hopefully it communicates the gist of things, if you need a working example let me know and I'll do my best to set one up.
I have tried this way and it worked for me
import CustomNextImage from '#commonComponentsDependent/CustomNextImage';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { FC } from 'react';
import ReactMarkdown from 'react-markdown';
import { Options } from 'react-markdown/lib/ast-to-react';
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
import remarkGfm from 'remark-gfm';
const SyntaxHighlighterDynamic = dynamic(() => import('./SyntaxHighlighter'));
import classes from './styles.module.css';
interface Props {
content: string;
}
type TCustomComponents = Options['components'];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const MdToHTML: FC<Props> = ({ content }) => {
const customComponents: TCustomComponents = {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
img(image) {
if (!image.src) return <></>;
return (
<div className={classes['img-container']}>
<CustomNextImage
src={image.src}
alt={image.alt}
/>
</div>
);
},
a({ href, children, node }) {
if (!href) return <></>;
if (
href.startsWith('/') ||
href.startsWith('https://lognmaze.com')
) {
return (
<Link href={href} prefetch={false} passHref>
<a>{children}</a>
</Link>
);
}
return (
<a
href={href}
target='_blank'
rel='noopener noreferrer'
>
{children}
</a>
);
},
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighterDynamic language={match[1]} PreTag='div' {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighterDynamic>
) : (
<code className={className} {...props} data-code-inline='true'>
{children}
</code>
);
},
};
return (
<ReactMarkdown
components={customComponents}
remarkPlugins={[remarkGfm]}
>
{content}
</ReactMarkdown>
);
};
export default MdToHTML;

Display Multiple Images from Json in ReactJS

I've managed to create a mockup json that i need to test a json request via axios on a react app.
For now, i can console.log the json file structure and can assign the data for the link.
The problem is that my content it's not being rendered correctly in the DOM via Map Method. the images are not appearing.
import {Link} from 'react-router-dom';
import axios from 'axios';
class DesignItem extends Component {
state = {
isLoading: true,
designs: [],
error: null
}
componentDidMount () {
axios.get('http://www.mocky.io/v2/5dadd81c2d0000e0f5e4bd57')
.then (res => {
console.log(res.data);
const designs = res.data;
this.setState({designs})
})
}
render() {
return (
<React.Fragment>
{this.state.designs.map(designs => (
// this one is appearing right as expected
<Link to={designs.productPage}>
<div className="design-item" key={designs.id}>
// this image doesn't appear. the URL is there but the image it's broken
<img src={designs.featUrl} alt="" />
</div></Link>
))}
</React.Fragment>
);
}
}
export default DesignItem;```
<React.Fragment>
{this.state.designs.map(designs => (
<Link to={designs.productPage} key={designs.id}> // I think the key must be put here instead on the div
<div className="design-item">
<img src={designs.featUrl} alt="" />
</div>
</Link>
))}
</React.Fragment>
Also upon checking the data, the image source was like this:
../images/products/alexandre-iii/0.jpg
Maybe that is why it is not showing up, if you could change the url to something like:
https://your-domain.com/public/images/products/alexandre-iii/0.jpg
It will show up.

No image uploaded "SRC" is undefined even with a check?

I'm facing a weird problem here I've created a check whether an image is uploaded or not. But for some reason, my "else" is not working.
Inside my main component "Fragrances" I'm looping through my API. And checking if the Array of images is empty return else show the image.
What am I doing wrong?
My code:
image component:
import React from 'react';
import NoPicture from 'components/NoPicture/NoPicture';
const Image = props => {
const { url } = props;
return url.length > 0 ? <img src={url} className="image" /> : <NoPicture />;
};
export default Image;
NoPicture component:
import React from 'react';
// No Picture
import NoPhotoImageURL from '../../images/no-photo.svg';
console.log(NoPhotoImageURL);
const NoPicture = () => (
<img
src={NoPhotoImageURL}
alt="No Photo"
className="image image--default"
/>
);
export default NoPicture;
Main component:
import React from 'react';
import { SITE_URL } from 'constants/import';
import Name from './name';
import Category from './category';
import Image from './image';
import Gallery from 'components/Gallery/gallery';
import Rating from './rating';
import Description from './description';
import Notes from './notes';
const Fragrances = props => {
const { FragranceData } = props;
return (
<section className="fragrances">
<div className="row">
{FragranceData.map(fragrance => {
console.log(fragrance);
const {
category,
description,
image,
gallery,
name,
rating,
notes,
Publish: isPublished,
} = fragrance;
const imageURL = image.path;
return isPublished ? (
<div key={fragrance._id} className="col-xs-12 col-sm-6">
<div className="fragrance">
<Name name={name} />
<Category category={category} />
<Image url={SITE_URL + imageURL} />
<Rating rating={rating} />
<Description description={description} />
<Notes notes={notes} />
<Gallery imageData={gallery} />
</div>
</div>
) : (
'Nothing published yet!'
);
})}
</div>
</section>
);
};
export default Fragrances;
Your question is not entirely clear on what exactly you are experiencing, but here is the most obvious problem in your code. You have this line in your Image component:
return url.length > 0 ? <img src={url} className="image" /> : <NoPicture />;
However, in your main component you are passing a concatenated string to the Image component:
<Image url={SITE_URL + imageURL} />
According to your comment, SITE_URL is the full URL, which will never be empty, so inside your Image component, url will always contain something, no matter what the value of imageURL is in the main component. Thus, url.length will always be greater than 0, and the img tag will render every time.
You will either need to pass the individual parts of the path down to the Image component separately, or move your check up into the main component.

React-bootstrap styling showing up before finished api call

I am making a small application in React that fetches a random image using Axios. I am using React-bootstrap to style the image, however a small white box is displayed for half of a second before the image is done loading. How can I resolve this?
This is my code:
import React, { Component } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';
import { Image, Button } from 'react-bootstrap';
const ROOT_URL = 'myurl'
export default class WhatDog extends Component {
constructor(props){
super(props);
this.state = { randomImg: '' };
}
componentDidMount(){
axios.get(ROOT_URL)
.then(res => {
const data = res.data.message
this.setState({ randomImg: data })
})
}
renderImage(){
return(
<div>
<Image src={this.state.randomImg} className="img" thumbnail/>
<Link to="/">
<Button bsStyle="danger" bsSize="large">Go back</Button>
</Link>
</div>
)
}
render() {
return (
<div className="App">
{
(this.state.randomImg === '')
? <div>
<h1>Loading...</h1>
</div>
: <div>
{this.renderImage()}
</div>
}
</div>
);
}
}
The browser will fire the onLoad event, after the image has been, you name it.. loaded so before that, set the visibility to hidden.. NOT display: none ! Because display: none will also prevent the loading.
The solution might look something like this
<Image
src={this.state.randomImg}
style={!this.state.imgVisible ? {visibility: 'hidden'} : {}}
onLoad={() => this.setState({ imgVisible: true })}
/>
Note: This is using inline styles and arrow functions, which is not best, but for simplicity of the demo its enough, you could also you a className instead, its up to you ;)
You got the idea...

Categories

Resources