3rd party Images gets broken in nextjs production environment - javascript

Images that get a response from API are showing broken on production env of next.js.
Here is my code
import Image from 'next/image';
//import PlaceHolderImage from "../public/images/placeholder.png";
interface IProps {
soldDate?: string;
price: string;
address: string;
bed: number;
bath: number;
cars: number;
sqm?: number | null;
image: any;
}
const PropertyCardInfo = (props: IProps): JSX.Element => {
return (
<div className="h-auto text-cpBlack border border-cpGreyLine mb-4">
<div className="w-full h-auto relative">
<Image
src={props.image}
alt={props.address}
width={360}
height={238}
layout="responsive"
/>
</div>
<div className="h-auto flex flex-col justify-between mt-1.5">
<div className="flex items-center justify-between pt-3.5 px-3.5">
<p className="font-semibold">{props.price}</p>
{props.soldDate && <p className="text-cpGrey text-sm">Sold {props.soldDate}</p>}
</div>
<a href="#" className="my-2 px-3.5 text-sm hover:text-cpOrange">
{props.address}
</a>
<div className="pb-3.5 px-3.5 flex text-sm font-semibold">
<p className="mr-2">
{props.bed}
<span className="ml-0.5">bed</span>
</p>
<p className="mr-2">
{props.bath}
<span className="ml-0.5">bath</span>
</p>
<p className="mr-2">
{props.cars}
<span className="ml-0.5">cars</span>
</p>
{props.sqm && (
<p className="mr-2">
{props.sqm}
<span className="ml-0.5">sqm</span>
</p>
)}
</div>
</div>
</div>
);
};
export default PropertyCardInfo;
I have whitelisted the domain and image URL domain in the next.config.js.
It also works well in development and local build environment.
But on deployment to UAT env, it show broken link and show the below error.
But if I pass same image through custom loader function then it worked.
const ImgLoader = ({ src }) => {
return props.image;
};
<Image
loader={ImgLoader}
src={props.image}
alt={props.address}
width={360}
height={238}
layout="responsive"
/>
Do I need to use custom loader for 3rd party images or Do I need to install sharp plugin ?
Please correct me if I am wrong.

Related

Template does'nt work with Tailwind in React

If I put the color directly in the tailwind class like "bg-cianTheme" it works. But if i use javascript template like "bg-${primaryColorTheme}" with the code above doesn't work. Why does it happen and how fix ?
The code:
import { BsGithub, BsLinkedin } from 'react-icons/bs'
export interface INewProfileCardProps {
photo: string
github: string
linkedin: string
colors: string[]
primaryColorTheme: string // tailwind refence collor
secondaryColorTheme: String //tailwind reference collor
terciaryColorTheme: string //tailwind reference collor
labelName: string
}
export function NewProfileCard({
photo,
github,
linkedin,
colors,
labelName,
}: INewProfileCardProps) {
const [primaryColorTheme, secondaryColorTheme, terciaryColorTheme] = colors
console.log(`bg-${primaryColorTheme}`)
return (
<div className="flex items-center justify-center">
<div>{/* <p className="text-[250px]">{'<'}</p> */}</div>
<div className=" relative h-[202px] w-[404px] rounded-xl bg-whiteIcon px-4 py-8 pt-2">
<div
className={`bg-${primaryColorTheme} relative flex h-full w-full`}
>
<img
className="absolute bottom-0"
src={photo}
alt="personal-photo"
></img>
</div>
<div className="absolute flex">
<div
className={`flex items-center justify-center font-bold text-${primaryColorTheme} bg-${primaryColorTheme} rounded-l-xl px-6 py-2`}
>
<BsGithub className="text-2xl" />
<p className="ml-3 text-lg">Git Hub</p>
</div>
<div
className={` bg-${secondaryColorTheme} ${primaryColorTheme} flex items-center justify-center rounded-r-xl px-6 py-2 font-bold`}
>
<BsLinkedin className="text-2xl" />
<p className="ml-3 text-lg">Linkedin</p>
</div>
</div>
</div>
<div>
{/* <p className="text-[250px]">
<span className={`text-${primaryColorTheme}`}>/</span>
{'>'}
</p> */}
</div>
</div>
)
}
I try to change the colors with variables in tailwind class with template, but doesn't work.
The problem is the postcss can't find that class when you have interpolated strings like that. You can add this to tailwind.config.js
safelist: ["bg-somecolor"]
or you can find a way to not use interpolation
In addition to pguardiano's answer, you may be able to achieve the same thing by calling the style attribute directly since postCSS only renders what is readily available in the template...
In your case, you can send the hex code directly to the variable and pass it to the style attribute. Example:
<div
className="relative flex h-full w-full"
style="{{ background: primaryColorThemeColor }}"
>
<img
className="absolute bottom-0"
src={photo}
alt="personal-photo"
/>
</div>
If you want to get your hands dirty and do things in a more interesting way, you can take advantage of Tailwind's theming functionality.
It is explained well in this video: https://www.youtube.com/watch?v=MAtaT8BZEAo.
Then you can update your CSS variables with whatever color is coming from your API I guess. Goodluck hacking your way in :)
Ref:
Updating CSS Variables with Javascript: https://css-tricks.com/updating-a-css-variable-with-javascript/

How to map an array inside JSON object using typescript?

I'm trying to get an array from a JSON object and then, map it in order to get the data.
Here is the data returned from an API:
{
project: [
{
_createdAt: '2022-12-15T16:45:57Z',
_id: 'cb39338d-4e6d-4c28-9a79-499afca392e6',
_rev: '974wCYB6EQ3xW9LGNZhQvU',
_type: 'project',
_updatedAt: '2022-12-27T04:55:54Z',
image: [Object],
linkToBuild: 'https://github.com/Arotiana137-51/charitty_to_portfolio_jsp',
summary: "This is a project I've done for learning purpose at the University. I've learned the basics of web programing with Java Server Pages ,Servelet ,....", technologies: [Array],
title: 'Charity '
}
]
}
And I wish to map this array in order to get elements from it inside this JSX element :
import React from "react";
import {motion} from 'framer-motion';
import { Project } from "../typing";
import { urlFor } from "../sanity";
type Props = {
projects:Project[];
};
function Projects({projects}: Props) {
console.log(projects);
return (
<motion.div
initial={{opacity:0}}
whileInView={{opacity:1}}
transition={{duration:1.5}}
className="h-screen relative flex overflow-hidden flex-col text-left md:flex-row max-w-full justify-evenly mx-auto items-center z-0">
<h3 className="absolute top-24 uppercase tracking-widest text-teal-400 text-2xl ">
Projects
</h3>
<div className="relative w-full flex overflow-x-scroll overflow-y-hidden snap-x snap-mandatory z-20">
{/*----------- HERE I TRY TO ACCESS THE ARRAY AND MAP IT DIRECTLY, LIKE IN JS-----------------------------------*/}
{ projects.project.map((project,i) => (
<div className="w-screen flex-shrink-0 snap-center flex flex-col space-y-5 items-center justify-center p-20 md:p-44 h-screen">
<motion.img
initial ={{
y: -300,
opacity:0
}}
transition={{duration: 1.2}}
whileInView = {{opacity:1 , y:0 }}
viewport={{ once: true}}
src={urlFor(project.image).url()}
alt="#"/>
<div className=" space-y-10 px-0 md:px-10 max-w-6xl ">
<h4 className="text-4xl font-semibold text-center">
Case study {i+1} of{projects.length}: <span className="underline decoration-teal-700"> {project?.title}</span>
</h4>
<div className="flex items-center space-x-2 justify-center">
{
project?.technologies.map((technology)=>(
<img
className="h-10 w-10"
key={technology._id}
src={urlFor(technology?.image).url()}
alt=""
/>
))
}
</div>
<p>{project?.summary}</p>
</div>
</div>
))}
</div>
<div className="w-full absolute top-[30%] bg-teal-800 left-0 h-[500px] -skew-y-12">
</div>
</motion.div>
);
}
export default Projects;
This normally works on js but my compiler return:
Server Error
TypeError: Cannot read properties of undefined (reading 'map')
because it still considers the prop as an object, even if I try to access the array at the code above, how can i solve it?
You are trying to do project?.technologies.map, but as i see at the JSON above , there is simply no "technologies" key.

TypeError: Cannot read properties of undefined (reading 'replaceAll')

Can anyone help me resolve this error?
error I'm getting: TypeError: Cannot read properties of undefined (reading 'replaceAll')
problem line: {user.userName.replaceAll(' ', '')}
i tried changing removing the replaceAll method since it wasn't a huge deal but the same error remained. I also tried writing it like as a regex but no luck:
{user.userName.replace(/\s+/g, '')}{' '}
Here's the all the code:
import React, { useEffect } from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { GoVerified } from 'react-icons/go';
import useAuthStore from '../store/authStore';
import { IUser } from '../types';
const SuggestedAccounts = () => {
const { fetchAllUsers, allUsers } = useAuthStore();
useEffect(() => {
fetchAllUsers();
}, [fetchAllUsers]);
return (
<div className="xl:border-b-2 border-gray-200 pb-4">
<p className="text-gray-500 font-semibold m-3 mt-4 hidden: xl:block">
Suggested Accounts
</p>
<div>
{allUsers.slice(0, 6).map((user: IUser) => (
<Link href={`/profile/${user._id}`} key={user._id}>
<div className="flex gap-3 hover:bg-primary p-2 cursor-pointer font-semibold rounded">
<div className="w-8 h-8">
<Image
src={user.image}
width={34}
height={34}
className="rounded-full"
alt="user profile"
layout="responsive"
/>
</div>
<div className="hidden xl:block">
<p className="flex gap-1 items-center text-md font-bold text-primary lowercase">
{user.userName.replaceAll(' ', '')}
<GoVerified className="text-blue-400" />
</p>
<p className="capitalize text-gray-400 text-xs">
{user.userName}
</p>
</div>
</div>
</Link>
))}
</div>
</div>
);
};
export default SuggestedAccounts;

404 when visiting page with dynamic route Gatsby

I'm trying to implement dynamic routing on a Gatsby site - I'm fetching launch data from the SpaceXAPI and creating a new page if a launch contains details. These details pages load correctly when you click on the 'View Details' link to view them from the homepage. When you access the page directly by its url, the page information is not found, resulting in a 404.
Why won't pages with this route load on their own? I'm also looking into ways to persist the state that I'm currently passing in to <Link>.
Repository: https://github.com/nikkipeel/gatsby-spacex
I'm not using <Router> or the createPages API...this is my project structure:
Accessing state through location on the page:
[name].js:
import * as React from 'react'
import moment from 'moment'
import Seo from '../../components/seo'
import ScrollToTop from '../../components/scrollToTop'
import Footer from '../../components/footer'
import '../../styles/tailwind.css'
const Launch = ({ location, name }) => (
<>
<main className="h-screen w-full bg-gray-900 text-white mx-auto">
<Seo title={name} />
{name && (
<>
<div className="flex flex-col md:w-3/4 lg:w-1/2 p-12 mx-auto text-base" key={name}>
<h1 className="mission-name tracking-wide font-bold text-2xl my-4">{name}</h1>
<strong className="tracking-wide text-xl my-2">Flight # {location.state.flight_number}</strong>
<div className="flex items-center my-2">
<strong className="text-xl mr-2">Mission: </strong>
<p className="text-base">{location.state.name}</p>
</div>
<div className="flex items-center my-2">
<strong className="text-xl mr-2">Launch Date: </strong>
<p>{moment(location.state.date_local).format('dddd, MMMM Do YYYY, h:mm:ss a')}</p>
</div>
{location.state.details && <p className="my-2">{location.state.details}</p>}
<a
href={location.state.links.wikipedia}
className="my-2 font-bold font-mono bg-clip-text text-transparent bg-gradient-to-t from-blue-500 via-blue-400 to-blue-300 transition duration-500 ease-in-out hover:text-blue-300 hover:underline pr-8"
>
Learn More
</a>
{location.state.links.video_link && (
<a
href={location.statelinks.video_link}
className="my-2 font-bold font-mono bg-clip-text text-transparent bg-gradient-to-t from-blue-500 via-blue-400 to-blue-300 transition duration-500 ease-in-out hover:text-blue-300 hover:underline p-2"
>
View Launch
</a>
)}
</div>
</>
)}
</main>
<ScrollToTop showBelow={250}></ScrollToTop>
<Footer></Footer>
</>
)
export default Launch
Setting state in <Link> in pastLaunches.js:
<Link
to={`/launches/${name}`}
state={{
name: name,
flight_number: flight_number,
date_local: date_local,
links: links,
rocket: rocket,
details: details
}}
className="mt-4 font-bold font-mono bg-clip-text text-transparent bg-gradient-to-t from-blue-500 via-blue-400 to-blue-300 transition duration-500 ease-in-out hover:text-blue-300 hover:underline w-48"
>
View Details
</Link>
Gatsby collection routes: https://www.gatsbyjs.com/docs/reference/routing/file-system-route-api/
Gatsby example client-only paths: https://github.com/gatsbyjs/gatsby/tree/master/examples/client-only-paths
Netlify issue with Gatsby and 404 pages: https://answers.netlify.com/t/gatsby-4-runtime-importmoduleerror-on-404-pages/46608

Could not reduce the size of the Image div - React Js , Tailwind

I am trying to Make a clone of the Book My show Application. I'm building the Cast and crew slider. I tried reducing the size of the image but the spacing between the image does not seem to reduce.
This is my js file containing the src, settings for the slider:
import React from "react";
import Slider from "react-slick";
import CastPoster from "../MovieCast/movieCast.component";
const Cast = (props) => {
const settings = {
infinite: true,
autoplay: false,
speed: 1500,
slidesToShow: 4,
slidesToScroll: 2,
InitialSlide: 0,
}
const CastImages = [
{
src:"https://in.bmscdn.com/iedb/artist/images/website/poster/large/simu-liu-2006167-13-05-2021-04-13-21.jpg",
name:"Simu Liu",
role:"as Shang-Chi"
},
{
src:"https://in.bmscdn.com/iedb/artist/images/website/poster/large/awkwafina-1093500-20-06-2018-12-05-44.jpg",
name:"Awkwafina",
role:"as Katy"
},
{
src:"https://in.bmscdn.com/iedb/artist/images/website/poster/large/tony-leung-iein105711-02-04-2018-13-07-58.jpg",
name:"Tony Leung Chiu-wai",
role:"as Wenwu / The Mandarin"
},
{
src:"https://in.bmscdn.com/iedb/artist/images/website/poster/large/michelle-yeoh-1473-24-03-2017-17-32-23.jpg",
name:"Michelle Yeoh",
role:"as Jiang Nan"
}
];
return (
<>
<div className="">
<Slider {...settings}>
{
CastImages.map((data) => (
<CastPoster {...data} />
))
}
</Slider>
</div>
</>
)
};
export default Cast;
This is the js file containing the rendering of the slider:
import React from "react";
const CastPoster = (props) => {
return (
<>
<div className="">
<img className="rounded-full w-32 h-32 " src={props.src} atl={props.name} />
<div>
<h3> {props.name} </h3>
<p> {props.role} </p>
</div>
</div>
</>
);
};
export default CastPoster;
And I have added it as a component in a page:
import React from "react";
import Cast from "../components/Cast/Cast.component";
import MovieHero from "../components/MovieHero/MovieHero.component";
import offerIcon from "./offericon.png";
const MoviePage = () => {
return (
<>
<MovieHero />
<div className="my-12 container px-4 lg:w-3/4 lg:ml-20">
<div className="flex flex-col items-start gap-3">
<h2 className="text-gray-800 font-bold text-2xl"> About the movie </h2>
<p> Shang-Chi and The Legend of The Ten Rings features Simu Liu as Shang-Chi, who must confront the past he thought he left behind when he is drawn into the web of the mysterious Ten Rings organization. The film is directed by Destin Daniel Cretton and produced by Kevin Feige and Jonathan Schwartz.</p>
</div>
<div className="my-8">
<hr />
</div>
<div>
<h1 className="text-gray-800 font-bold text-2xl pb-4"> Applicable Offers </h1>
<div className="flex items-start gap-2 bg-yellow-100 border-yellow-400 border-2 border-dashed rounded-md p-3 w-96">
<img className="h-6" src={offerIcon}/>
<div className="flex flex-col items-start">
<h3 className="relative -top-1 text-gray-900 text-md font-semibold"> Filmy Pass </h3>
<p className="text-gray-600 -top-1 text-sm"> Get Rs.75* off on 3 movies you buy/rent on Stream. Buy Filmy Pass #Rs.99 </p>
</div>
</div>
</div>
<div className="my-8">
<hr />
</div>
<div>
<h3> Cast </h3>
<div>
<Cast />
</div>
</div>
</div>
</>
)
};
export default MoviePage;
The result:
This is the result of the code
I want to reduce the spacing between the images. Thank you.
The space between your images is determined by the amount of slides you want to show and the width of the slider div. To decrease the space between the images reduce the width of the slider or show more images.
Your Cast component could look like this
<div className="w-full">
<Slider {...settings} className="w-1/2">
{
CastImages.map((data) => (
<CastPoster {...data} />
))
}
</Slider>
</div>

Categories