I am unable to show data in my NextJS app using Sanity - reactjs

Though the data is showing in the console but I am missing something. I am new to NextJS and Sanity.io. So Kindly help. Nextjs code is not showing data in the frontend.
This is the NextJs code:
import React from "react";
// import Layout from '../components/Layout';
import client from '../utils/client';
export const TermsAndPolicy = (props) => {
return (
<>
<div className="ease-in">
<div>
<h1 className="text-3xl font-medium text-center my-4">Terms and Conditions</h1>
<h4 className="text-xl mx-8 py-8 ">
<span>Last Updated:{props.terms.dateUpdated}</span>
</h4>
</div>
<div>
<div>
<h2>{props.title}</h2>
</div>
<p className="md:text-justify text-center mx-8 py-8">
{props.body}
</p>
</div>
</div>
</>
);
};
export default TermsAndPolicy;
export const getServerSideProps = async () => {
const query = `*[_type == "terms"]{
title,
subHeading,
dateUpdated,
url,
body
}`;
const terms = await client.fetch(query)
console.log(terms);
return {
props: {
terms
}
};
}
I have added the NextJs code above which shows that I have called the client and connected the app. But somehow I am unable to show the data from the backend into the frontend. Data in the console is showing as you can see below! So therefore it is connected properly. The data below is the data showing in console:
But data is not showing in the website. It is showing blank instead.

Related

Why is Next.js giving me an error of undefined when I am trying to pull data from firebase firestore

This error makes no sense at all. This is the error I get when trying to get data from my firestore database.
TypeError: Cannot read property 'map' of undefined
I think it is a firebase firestore related error but it is giving me that error which makes it hard for me to know what exactly is wrong because I know that is not the problem. This is where page where I have the code where I am extracting the data using getStaticProps
import img from "./img.png";
import Image from 'next/image';
import styles from "../styles/Card.module.css";
import { db } from "../firebase";
import { collection, getDocs } from 'firebase/firestore';
export const getStaticProps = async () => {
const reference = collection(db, "students");
const data = await getDocs(reference);
const theData = data.docs.map(doc => ({...doc.data(), id: doc.id}));
console.log(data.name);
return {
props: {students: data}
}
}
function Card({students}) {
return (
<div className={styles.cardContainer}>
{students.map(student => (
<div className={styles.card}>
<div className={styles.first}>
<Image src={student.img} className={styles.imgr} width={200} height={150} alt="ima" placeholder='yeah bitch' />
</div>
<div className="second">
<h3>{student.name}</h3>
<p>{student.surname}</p>
</div>
</div>
))}
</div>
)
}
export default Card
This seems to me more like a firestore related problem not a looping problem. Where could I be going wrong?.
Based on your comment it runs just fine in useEffect but now it is failing. My guess is that it is failing on the server, and not on the client. useEffect does not ever run on the SSR. This is purely a hunch based on the data I have.
You could research how to check if you are on the server, and if so pass an empty array so students is not undefined. Or you could just always check for undefined and replace it with an empty array.
function Card({students}) {
const definedStudents = students ?? []
return (
<div className={styles.cardContainer}>
{definedStudents.map(student => (
<div className={styles.card}>
<div className={styles.first}>
<Image src={student.img} className={styles.imgr} width={200} height={150} alt="ima" placeholder='yeah bitch' />
</div>
<div className="second">
<h3>{student.name}</h3>
<p>{student.surname}</p>
</div>
</div>
))}
</div>
)
}

Can someone tell me why my app crashes when I refresh the page?

I added a weather component in my app that fetches weather from open weather map. It works fine until I refresh the page, then it breaks.
If I comment the weather component out when refreshing and then add it back in when loaded it renders and works.
I'm not sure what's causing this error.
Here's some images of the console after refreshing for reference.
It seems to be undefined when refreshed. What's causing this issue?
// Weather component is called as normal in Home page
<div className="main-section-one">
<Weather />
<ToDoWidget />
</div>
import React, { useEffect, useState } from 'react'
//CSS
import '../css/Weather.css'
function Weather() {
// API
const URL = 'https://api.openweathermap.org/data/2.5/weather?q=barcelona&appid=APIKEY';
// State
const [weatherDetails, setWeatherDetails] = useState({});
async function getWeather() {
let fetchUrl = await fetch('https://api.openweathermap.org/data/2.5/weather?q=barcelona&appid=APIKEY&units=metric');
let data = await fetchUrl.json()
setWeatherDetails(data)
}
//Use Effect
useEffect(() => {
getWeather();
}, [])
return (
<div className="weather-container">
<div className="weather-one">
<div className="city">
<h3>Barcelona</h3>
<h1 className='temp'>{weatherDetails.main.temp}°C</h1>
</div>
<div className="current-weather">
<h3 className='current'>Sunny</h3>
</div>
</div>
<div className="weather-two">
<div className="">
<p>{weatherDetails.main.feels_like}°C</p>
<p className='weather-details'>Feels Like</p>
</div>
<div className="">
<p>{weatherDetails.main.humidity}%</p>
<p className='weather-details'>Humidity</p>
</div>
<div className="">
<p>{weatherDetails.wind.speed} MPH</p>
<p className='weather-details'>Wind Speed</p>
</div>
</div>
</div>
)
}
export default Weather
The main and wind properties may be undefined. Secure it.
<h1 className='temp'>{weatherDetails.main?.temp}°C</h1>
^^^ optional chaining
<p>{weatherDetails.wind?.speed} MPH</p>
Reference: Optional chaining

Error: React Hook "useDocumentOnce" is called conditionally. React Hooks must be called in the exact same order in every component render

I was making an app using NextJS, TailwindCSS, Firebase and It is working 100% correctly on local host but on deploying on Vercel, I get the following error :
15:18 Error: React Hook "useRouter" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks
17:39 Error: React Hook "useDocumentOnce" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks
I am not able to understand why I get this error when deploying my app to Vercel.Maybe it's something related to redirect link in google API console
Here's my [id].js file :
import TextEditor from "../../components/TextEditor";
import Button from "#material-tailwind/react/Button";
import Icon from "#material-tailwind/react/Icon";
import { useRouter } from "next/dist/client/router";
import { db } from "../../firebase";
import { useDocumentOnce } from "react-firebase-hooks/firestore";
import { getSession, signOut, useSession } from "next-auth/client";
import Login from "../../components/Login";
function Doc() {
const [session, loading] = useSession();
console.log(session);
if (!session) return <Login />;
const router = useRouter();
const { id } = router.query;
const [snapshot, loadingSnapshot] = useDocumentOnce(
db.collection("userDocs").doc(session.user.email).collection("docs").doc(id)
);
// Redirect if user tries to access a URL they do not have access to...
if (!loadingSnapshot && !snapshot?.data()?.fileName) {
// Filename will not be present if the user doesnt have access...
router.replace("/");
}
return (
<div>
<header className="flex justify-between items-center p-3 pb-1">
<span onClick={() => router.push("/")} className="cursor-pointer">
<Icon name="description" size="5xl" color="blue" />
</span>
<div className="flex-grow px-2">
<h2 className="text-lg text-left">{snapshot?.data()?.fileName}</h2>
<div className="flex items-center text-sm -ml-1 h-8 text-gray-600 space-x-1">
<p className="option">File</p>
<p className="option">Edit</p>
<p className="option">View</p>
<p className="option">Insert</p>
<p className="option">Format</p>
<p className="option">Tools</p>
</div>
</div>
<Button
color="lightBlue"
buttonType="filled"
size="regular"
className="hidden md:!inline-flex h-10"
rounded={false}
block={false}
iconOnly={false}
ripple="light"
>
<Icon name="people" size="md" /> SHARE
</Button>
<img
onClick={signOut}
className="cursor-pointer h-10 w-10 rounded-full ml-2"
src={session.user.image}
alt=""
/>
</header>
<TextEditor />
</div>
);
}
export default Doc;
export async function getServerSideProps(context) {
const session = await getSession(context);
return {
props: {
session,
},
};
}
You have early return before calling useDocumentOnce on line
if (!session) return <Login />
Which is not good as the error says. You should make sure that you always render the same amount of hooks on each render. In your case you are calling 3 hooks. But if session is not defined you only render 1 hook. That is the problem you have to resolve.

getStaticProps not working from components folder

Recently I made a question about this problem: typeError: Cannot read property 'map' of undefined.
I want to use a component with getStaticProps and put it in my pages/index.js, but I can't with my current code. BUT, if I put this component as a page (pages/component.js) and open like a different page it just work as it should do.
The component Galery.js code:
import styles from '../styles/galery.module.css'
import Image from 'next/image'
import Link from 'next/link'
import photo from '../public/01.png'
export const getStaticProps = async () => {
const res = await fetch('https://my-json-server.typicode.com/Leterinho/PortfolioInteriorDesign/card');
const datas = await res.json();
return {
props: { datas }
}
}
const Galery = ({ datas }) => {
return (
<div className={styles.galeryPage}>
<h1 className={styles.title}>Projetos</h1>
<div className={styles.galery}>
<div className={styles.categoryWrapper}>
<h4 className={styles.subTitle}>Escritório</h4>
<div className={styles.lineWrapper}>
<a className={styles.leftArrow}>❮</a>
<div className={styles.line}>
{datas.map((data) => (
<div className={styles.imageBox}>
<Image src={photo} width={400} height={200} layout="responsive" lazy="true" placeholder="blur" />
<div className={styles.linkContent}>
<span className={styles.name} key={data.id}>{data.name}</span>
<Link href=""><a className={styles.link}>Veja Mais!</a></Link>
</div>
</div>
))}
</div>
<a className={styles.rightArrow}>❯</a>
</div>
</div>
</div>
</div>
);
}
export default Galery;
API link: https://my-json-server.typicode.com/Leterinho/PortfolioInteriorDesign/card
And this is the structure that I would like to have:
Desirable Structure
And this is the structure that works as a page:
Structure that works
What I should do to work as I planned?
Data fetching methods like getStaticProps can only be used from page components (components inside pages folder). I'd suggest you fetch the data at the page level in index.js, and pass it down to your Galery component.
juliomalves is correct! Thanks.

Caching in Gatsby JS

I have this Gatsby app where when I visit home page everything loads at first including the Testimonials section. However, when I visit another page, for instance the Blog list page and then click on the link back to homepage the data on Testimonials component won't load and you will see a blank area of the app where the Testimonials section is placed. In order to see the Testimonials list, you will have the refresh the page again.
For the record the data on my Testimonials component are being pulled out on Strapi JS that is deployed on Heroku.
So far I got this on my index.js:
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/Layout"
import Header from "../components/Header"
import Testimonials from '../components/Testimonials'
import Blogs from '../components/Blogs'
import SEO from '../components/SEO'
export default function Home({ data }) {
const {
allStrapiBlogs: { nodes:blogs },
} = data
return (
<>
<SEO />
<div className="main-container">
<Layout>
<Header />
<Testimonials title="Testimonials" />
<Blogs title="Latest Blogs" blogs={blogs} showAllBlogLinks/>
<Map />
</Layout>
</div>
</>
)
}
export const query = graphql`
{
allStrapiBlogs(filter: {featured: {eq: true}}, sort: {fields: published_date, order: DESC}, limit: 6) {
nodes {
id
title
content
slug
published_date(formatString: "MMMM DD, YYYY")
featured_image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
And then on my Testimonials.js component:
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
import Image from "gatsby-image"
import { FaStar } from "react-icons/fa"
import Title from './Title'
const query = graphql`
{
allStrapiTestimonials {
nodes {
id
name
cite
text
photo {
childImageSharp {
fluid{
...GatsbyImageSharpFluid_withWebp
}
}
}
}
}
}
`
const Testimonials = ({ title }) => {
const data = useStaticQuery(query)
const { allStrapiTestimonials: { nodes:testimonials } } = data
return (
<div className="testimonial-section section-padding" id="testimonial" data-aos="zoom-in">
<div className="container">
<div className="row">
<div className="col-lg-12">
<div className="section-title-two center">
<Title title={title} />
</div>
</div>
</div>
<div className="testimonial-wrap row">
<div className="testimonial-slider owl-carousel">
{ testimonials.map(item => {
const { id, name, cite, text, photo } = item
return(
<div className="col-xl-8 col-lg-10 col-12 ml-auto mr-auto" key={id}>
<div className="testimonial-item mt-40">
<div className="testimonial_img">
<Image fluid={photo.childImageSharp.fluid} alt={name} style={{ position: "absolute", overflow: "visible", display: "block", width: "211px", height: "207px" }} />
</div>
<div className="testimonial_content xs-mt-40">
<div className="testimonial_content_item mb-30">
<div className="testimonial_content__pro">
<h4 className="mb-10">{ name }</h4>
<p>{ cite }</p>
</div>
<ul className="d-none d-sm-inline-block">
<li><FaStar></FaStar></li>
<li><FaStar></FaStar></li>
<li><FaStar></FaStar></li>
<li><FaStar></FaStar></li>
<li><FaStar></FaStar></li>
</ul>
</div>
<div>
<p>{ text } </p>
</div>
</div>
</div>
</div>
)
})}
</div>
</div>
</div>
</div>
)
}
export default Testimonials
Any idea what's causing this error? How can I fix it?
I've faced a similar issue a few months ago and the fix depends strictly on the implementation and your code. Basically, what is happening is that React's doesn't understand that he needs to rehydrate some components because pointing to some global objects as window or document of the DOM, outside the React's ecosystem (without using states) may block that rehydration, in your cause, because of jQuery.
All the possible solutions that bypass this issue will be patches (like trying to add the cache). The ideal solution would avoid using jQuery, which points directly to the DOM, with React, which manipulates the virtual DOM (vDOM).
There's nothing wrong with the code you've shared, however, based on some other questions that you did, you are using jQuery and using the window object, which prevents the rehydration of some React components. You should get rid of jQuery or using some React-based approach. Something like this should do the trick to force a loader across the whole site:
const Layout = ({ children }) => {
const [loader, setLoader]=useState(true);
useEffect(()=>{
setTimeout(()=> {
setLoader(false)
}, 400)
}, [])
return <section className={`site__wrapper`}>
<Header />
<main>{loader ? <Preloader/> : children}</main>
</section>;
};

Resources