Turbo Start Sanity - Template
The battle-tested Sanity template that powers Roboto Studio's websites
Go to Turbo Start Sanityimport React, { useEffect, useState, useLayoutEffect } from 'react';
import { Link } from "react-router-dom";
import Header from "../components/Header";
import "./Home.css";
import {Carousel, Card, Image} from 'antd';
import {client} from "../lib/client";
import imageUrlBuilder from '@sanity/image-url'
const Home = () => {
const [products,setProducts]= useState([]);
const [bannerData,setBannerData]= useState([])
const builder = imageUrlBuilder(client)
function urlFor(source) {
const url= builder.image(source)
return url
}
useEffect(() => {`client.fetch(
*[_type == "featured"]{
name,
genre,
image
}).then((data)=>setProducts(data))`
}, [])
useLayoutEffect(() => {`client.fetch(
*[_type == "banner"]{
image
}).then((data)=>setBannerData(data))`
}, [])
return(
<>
<div className="container">
<Header/>
<Carousel autoplay className="carousel">
{bannerData?.map((data) => {
return <img src={urlFor(data.image.asset).url()} className="carousel-img" alt="carousel"></img>;
})}
</Carousel>
<div className="cards">
{products.map((product)=>{
return(
<Card className="card" key={product._id}>
<Link to="/categories" state={product.genre} className="link" style={{textDecoration:"none"}}>
<img src={urlFor(product.image.asset).url()} alt={product.name} className="card-content"/>
<h4>{product.name}</h4>
</Link>
</Card>
)
})}
{/*<Card className="card">*/}
{/* <h1>Shop By Category</h1>*/}
{/*<div className="card-content">*/}
{/* {catCard.map((e) => {*/}
{/* return (*/}
{/* <img*/}
{/* src={e}*/}
{/* alt="category"*/}
{/* className="card-category"*/}
{/* onClick={() => console.log("beauty")} key={e}*/}
{/* ></img>*/}
{/* );*/}
{/* })}*/}
{/* <br />*/}
{/* <Link to="/" className="link">*/}
{/* Shop All*/}
{/* </Link>*/}
{/*</div>*/}
{/*</Card>*/}
</div>
</div>
</>
)
}
export default Home;
Query looks like client.fetch(`*[_type == "banner"]{ image:image.asset->url }`).then((data)=>setBannerData(data)) }, [])
*[_type == "banner"] { "image": image.asset->url }
{ name: 'image', title: 'Image', type: 'array', of: [{ type: 'image' }], options: { hotspot: true, } },
import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import Header from "../components/Header"; import "./Home.css"; import { Carousel, Card, Image } from "antd"; import { client } from "../lib/client"; import imageUrlBuilder from "@sanity/image-url"; const urlFor = (source) => imageUrlBuilder(client).image(source); const query = `{ "featured": *[_type == "featured"]{name, genre, image}, "banner": *[_type == "banner"]{image} }`; const Home = () => { const [products, setProducts] = useState([]); const [bannerData, setBannerData] = useState([]); useEffect(() => { client .fetch(query) .then(({ featured, banner }) => { setProducts(featured); setBannerData(banner); }) .catch((error) => console.log(error)); }, []); return ( <> <div className="container"> <Header /> <Carousel autoplay className="carousel"> {bannerData?.map((data) => { return ( <img src={urlFor(data.image).url()} className="carousel-img" alt="carousel" ></img> ); })} </Carousel> <div className="cards"> {products.map((product) => { return ( <Card className="card" key={product._id}> <Link to="/categories" state={product.genre} className="link" style={{ textDecoration: "none" }} > <img src={urlFor(product.image).url()} alt={product.name} className="card-content" /> <h4>{product.name}</h4> </Link> </Card> ); })} </div> </div> </> ); }; export default Home;
imagefield to generate the urls. That will also make hotspot and crop work if you have that enabled. And you can use its methods to control dimensions and other things. • I’ve combined the queries into one, so that you don’t need to fetch 2 times. Also,
useLayoutEffectwill block your DOM rendering. Not sure if that’s the intention, but I’d generally stay clear of it (also, you should probably look into a framework that’s able to server render this if you’re planning to run this on the web. Next.js is a good choice)• I haven’t actually run this code, but let me know if it works, or what errors you get.
image
<Carousel autoplay className="carousel"> {bannerData?.map((data) => { return data.image.map(img => ( <img key={img._key} src={urlFor(img).url()} className="carousel-img" alt="carousel" ></img> )); })} </Carousel>
{ name: 'image', title: 'Image', type: 'array', of: [{ type: 'image' }], options: { hotspot: true, } },
{ name: 'images', title: 'Images', type: 'array', of: [{ type: 'image', options: { hotspot: true, } }], },
import React, { useEffect, useState } from "react"; import imageUrlBuilder from "@sanity/image-url"; import { client } from "../lib/client"; const urlFor = (source) => imageUrlBuilder(client).image(source); const query = `{ "featured": *[_type == "featured"]{name, genre, image}, "banner": *[_type == "banner"][0]{image} }`; const Home = () => { const [products, setProducts] = useState([]); const [bannerData, setBannerData] = useState([]); useEffect(() => { client .fetch(query) .then(({ featured, banner }) => { console.log({ featured, banner }); setProducts(featured); setBannerData(banner); }) .catch((error) => console.log(error)); }, []); return ( <> <div className="container"> <div autoplay className="carousel"> <img src={urlFor(bannerData.image).url()} className="carousel-img" alt="carousel" ></img> </div> <div className="cards"> {products.map((product) => { return ( <div className="card" key={product._id}> { product.image && product.image.map(img => ( <img key={img._key} src={urlFor(img).url()} alt={product.name} className="card-content" /> )) } <h4>{product.name}</h4> </div> ); })} </div> </div> </> ); }; export default Home;
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import Header from "../components/Header";
import "./Home.css";
import { Carousel, Card, Image } from "antd";
import { client } from "../lib/client";
import imageUrlBuilder from "@sanity/image-url";
const urlFor = (source) => imageUrlBuilder(client).image(source);
{
"featured": *[_type == "featured"]{name, genre, image},
"banner": *[_type == "banner"][0]{image}`}`;`
const Home = () => {
const [products, setProducts] = useState([]);
const [bannerData, setBannerData] = useState([]);
useEffect(() => {
client
.fetch(query)
.then(({ featured, banner }) => {
console.log({ featured, banner });
setProducts(featured);
setBannerData(banner);
})
.catch((error) => console.log(error));
}, []);
return (
<>
<Header/>
<div className="container">
<Carousel autoplay className="carousel">
<img
src={urlFor(bannerData.image).url()}
className="carousel-img"
alt="carousel"
></img>
</Carousel>
<div className="cards">
{products.map((product) => {
return (
<Card className="card" key={product._id}>
<Link>
{
product.image &&
product.image.map(img => (
<img
key={img._key}
src={urlFor(img).url()}
alt={product.name}
className="card-content"
/>
))
}
<h4>{product.name}</h4>
</Link>
</Card>
);
})}
</div>
</div>
</>
);
};
export default Home;
This is a multiline code snippet
bannerDatato be an empty array by default. Looking through your code it seems to me that maybe you want to rethink your data modelling a bit as well? Since you have a
Carouselyou probably want
bannerto have an array of images, and not just the one image it has now? Anyways, given the data structures you have now, I think this code should work.
const query = `{ "featured": *[_type == "featured"]{name, genre, image}, "banner": *[_type == "banner"][0]{image} // [0] will get the banner document with the last update }`; const Home = () => { const [products, setProducts] = useState([]); const [bannerData, setBannerData] = useState({}); // CHANGE THIS useEffect(() => { client .fetch(query) .then(({ featured, banner }) => { setProducts(featured); setBannerData(banner); //console.log({ featured, banner }); }) .catch((error) => console.log(error)); }, []); return ( <> <Header /> <div className="container"> {/* CHANGE FROM HERE */} {bannerData?.image && <Carousel autoplay className="carousel"> <img src={urlFor(bannerData.image).url()} className="carousel-img" alt="carousel" ></img> </Carousel>} {/* …TO HERE */} <div className="cards"> {products.length > 0 && products.map((product) => { return ( <Card className="card" key={product._id}> <Link> { product.image && product.image.map(img => ( <img key={img._key} src={urlFor(img).url()} alt={product.name} className="card-content" /> )) } <h4>{product.name}</h4> </Link> </Card> ); })} </div> </div> </> ); };
bannerI’d probably make a
siteSettingsor a
pagetype with an object called
bannerthat has an array of
imagecalled
imagesin it.
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.
Get more help in the community Slack
Topic | Categories | Featured | Replies | Last Updated |
---|---|---|---|---|
How to turn PortableText into plain text in Javascript? | Dec 7, 2020 | |||
Custom Document Views - Is it Even Possible to Use the Structure Builder? | Apr 21, 2022 | |||
Clarification on creating drafts from a published document in Sanity.io. | Dec 14, 2023 | |||
Trouble updating Sanity version, seeking help and guidance. | Jan 24, 2024 | |||
GROQ query for getting references from arrays in another array in Sanity.io | Not featured | Apr 9, 2020 | ||
Upgrading to Sanity v3 causing ECONNRESET error, resolved by updating Node version | Not featured | May 23, 2023 | ||
How to fetch an array of images using groq in Sanity.io | Not featured | May 21, 2023 | ||
Error: unable to resolve image URL from source (undefined) | Sep 11, 2022 | |||
Discussion about using Sanity.io as a backend solution for small projects and its features | Not featured | Apr 18, 2020 | ||
Clarification on obtaining image orientation and aspect ratio in Sanity.io | Not featured | Jul 22, 2020 |
The battle-tested Sanity template that powers Roboto Studio's websites
A Next.js starter template with Next.js 15, Tailwind CSS, shadcn/ui, and Sanity CMS with Live Editing. Get production-ready React components with matching Sanity schemas and queries. Build dynamic pages faster while keeping full control over customization.
A new brand identity to represent a more mature company, to signify The Swaddle’s evolution from publisher to production house, combined with an easier to navigate platform that can surface multiple content types - drawing readers through The Swaddle’s content offering.