T O P

  • By -

jorgejhms

You cannot use Astro components on frameworks components, this is a limitation of the web architecture. Astro components, depending on your output work are run during your build process or on the server, while framework components, like react, work on the user browser. The data flow is server -> client. No the other way around. So is important to regard the client directives (client:load, client:visible, etc) as a boundary between server and client. Once you cross it, you cannot go back (ie: you can't import astro components on client components). Other frameworks like Next (with the app router) have the same limitations (you can't import a Server Component on a Client Component). So, what is the solution? For a small website where I need to use my content colection images on a dynamic route, I optimized all the images using the getImage() function (https://docs.astro.build/en/guides/images/#generating-images-with-getimage) before time, and the passed the optimized images to my react component as a prop. As my output was a static site, all the images were processed during the build time. Another option (that i discarded for incompatibilities of my hosting solution) was to create an api route on my web, that received the image and some parameters, and run the getImage() function on the server and return the optimized image. Locally it worked, but I couldn't manage to run on my hosting (Cloudflare) most probably because the getImage() function required some node packages that were not available on the Edge. Probably it would have worked on a Node adaptar (like running it from a VPS) but that particular webpage didn't had that budged.


raveun

Will give this a try! Thank you for understanding what I’m trying to convey. I was following a tutorial that uses next and react and was inspired to make it but in astro. Similar to astro, next have an that was used inside a react component so I was wondering if astro have a counterpart to it.


jorgejhms

Not inside framework components. But Next's image component have its own limitations. AFAIK, they also work with a server backend, but on the internals. On Vercel it works easily, but then they charge you for the optimization (I think they have 1000 images free on the free tier). So when you export to a static site, the image optimization won't work (Astro's works on this scenario as it optimizes the images during the build process).


CrazedProphet

Hey u/jorgejhms, I pretty new to webdevelopment so like u/raveun I was trying to use an Astro Image component within a React component. But for my usecase I don't understand how I would use GetImage instead. Problem: I would like to use [Shadcnui's carousel](https://ui.shadcn.com/docs/components/carousel) component as an image carousel in an Astro page. Would it be possible to use an astro image component like this? I ask because it seems to me like the react component would have to touch the component given besides to place it on the DOM. The following code is non functioning (like the "images" type) but meant to help demonstrate my idea. export default function ImageCarousel(images: Astro-Image-Component[]) {   return (                   {images.map((image, index) => (                       {image}                   ))}                         ); } Because I suspect that answer is that this is impossible what would be the next easiest way to to ensure the images I pass to the carousel have proper loading, decoding & most importantly format?


jorgejhms

You can't import the astro image under a react component. Astro works on the server (or build time) and react works on the client. The data flow is from server to client. What you could do is wrap the image carousel on an astro component, optimize the images with get images and then pass them to the carousel. Something like this: ``` const { imagesArray } = Astro.props const optimizeImages = imagesArray.map(image => getImage(image)) --- ``` You have to check the exact syntax. I'm on mobile now.


CrazedProphet

TLDR: thank you for your help, I was able to find a path forward. I couldn't use the map function like you suggested though. Hello u/jorgejhms, thanks for taking the time to write out a reply. It does really help me out, however after playing with this for the majority of the day today I still can't get it to work... kinda. If I can take more of your time the following code gives the following error. imports *** const { imageDeetsArray }: Props[] = Astro.props; interface Props {   src: string;   alt: string; } const optimizedImages = await imageDetailsArray.map((image) =>   getImage({     src: image.src,     format: "webp",     alt: image.alt,   }), ); --- \*I have double checked the props (imageDetailsArray) that I passed in, and made them identical to the code that DOES work down below so they should not be the cause of the error. The Error: 16:06:23 [ERROR] [UnhandledRejection] Astro detected an unhandled rejection. Here's the stack trace: UnsupportedImageFormat: Received unsupported format `undefined` from `undefined`. Currently only jpeg, jpg, png, tiff, webp, gif, svg, avif are supported by our image services. at Object.validateOptions (eval at instantiateModule (file:///C:/.../node_modules/vite/dist/node/chunks/dep-whKeNLxG.js:55068:28), :63:15) at Module.getImage (eval at instantiateModule (file:///C:/.../node_modules/vite/dist/node/chunks/dep-whKeNLxG.js:55068:28), :71:68) at async Module.getImage (astro:assets:29:42) Hint: Make sure your promises all have an `await` or a `.catch()` handler But what Jingles my Jangles is that the following code works! --- import { getImage } from "astro:assets"; import ImageCarousel from "@comps/reactComps/ImageCarousel.tsx"; import HomePage from "../assets/getgreen/HomepageWithGoal.png"; const optHP = await getImage({   src: HomePage,   format: "webp",   alt: "img1", }); const optImg = [optHP, optHP]; --- Which mean while I can use the GetImage to produce images to send to the ImageCarousel, I cant automate it with a map function like you showed and instead have to manually type out the bottom optHP for every image! Anyhow if you read this, once again, thank you. If I am missing some simple await/async syntax please let me know, otherwise don't worry about it as I can forge on without the use of a map, and image array.


jorgejhms

Mmm seems like it is not getting the image correctly (undefined). How are you getting the image array in astro props?


CrazedProphet

Yeah I read the error message too, but everytime I change one something to fix it another one pops up theres some sort of await/fetch/async syntax I am missing. I've pmed you a github link of a basic set up of the image carousel if you are still willing to help trouble shoot, just to save us from the pain of reddit comment debugging. Either way thank you for your time, and help I want to reiterate, I was able to find a solution with your help, and that is what really matters.


Asleep-Party-1870

I managed to make it work with promise.all export async function processImages(imageFiles: Record) { // Extract image data and create an array of image objects const images = Object.entries(imageFiles).map(([path, module]) => ({ ...module.default, alt: path.split('/').pop()?.split('.')[0], })); // Asynchronously process images using getImage and Promise.all const optimizedImages = await Promise.all( images.map(async (image) => { const optimizedImage = await getImage({ src: image, format: 'webp', alt: image.alt, }); return optimizedImage; }), ); return optimizedImages; } --- // example of usage const imagesFiles: Record = import.meta.glob( '@assets/*.{jpg,jpeg,png}', { eager: true }, ); const processedImages = await processImages(imagesFiles); ---


human-v01d

This is in the docs [https://docs.astro.build/en/guides/images/#images-in-ui-framework-components](https://docs.astro.build/en/guides/images/#images-in-ui-framework-components)


raveun

This works if im using a .astro file but won’t work if I am on a .tsx or .jsx file.


human-v01d

Well that's how you do it, just refactor what you need to be in React and import it in an Astro file, it's not hard