How to get component loaded state in Next.js? - javascript

I am working on a simple Pokedex that shows all pokemon, I am displaying all the cards by using a map function on an array of pokemon objects like this:
{pokemons.results.map((el, i) => {
return (
<div key={i} className="lg:w-1/4 md:w-1/2 p-4 w-full">
<Link href={"/"}>
<a className="block relative rounded-lg overflow-hidden hover:cursor-pointer hover:shadow-xl hover:shadow-poke-blue/50 p-4 bg-poke-blue group">
<img
alt="ecommerce"
className="object-cover object-center w-full block"
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${el.url
.replace("https://pokeapi.co/api/v2/pokemon/", "")
.replace("/", "")}.png`}
height="400px"
onError={addDefaultSrc}
/>
<div className="mt-4">
<h2 className="group-hover:underline text-white text-center title-font text-lg font-medium uppercase">
{el.name}
</h2>
</div>
</a>
</Link>
</div>
);
})}
there is an image tag in the div of the card which displays the image of the pokemon like this:
I also added the functionality to search pokemon based on the name. The problem is as soon as the state changes the images don't change immediately which makes sense since the images don't get downloaded instantly. For a few minutes, it shows the image of the previously loaded pokemon image at the same place.
So I need help to show a loader for the time till all the images have loaded. I will use a loader that I already have I need to know how to get the event of all images loaded.
Thanks for reading!

There is an onLoad event on the img tag you should be able to just add a loaded property on each item in the local copy of the data, then just updated the loaded property onLoad and then make a derived loaded variable
const loaded = images().every(img => img.loaded)
Also #Chris G's message about the keys is entirely correct and should be followed, I was just answering the question

Related

How do I fire a function from when a button is clicked on one html page, to load content dynamically on another html page?

I am building an app using HTML, CSS and vanilla JS to help learn my way around the languages and I have been stuck on a problem for a while.
Basically I have an index.html page that populates with football fixtures when a button is clicked. This works fine.
Then, when a certain fixture button is clicked, I want to pull specific data for that specific fixture and display it on a different page when loaded. The button click loads a new html page, but then should populate that page with the relevant fixture data.
Through lots of trial and error, only part of the function works. There is quite a lot of code from between HTML and JS so I don't want to share too much to make this more complex, as I am sure I am probably missing something simple.
But, here is the code that picks up the unique fixture id from the fixture card that is clicked on the index.html page.
const matchButton = document.querySelectorAll(".match-button");
for (i = 0; i < matchButton.length; i++) {
matchButton[i].addEventListener("click", (e) => {
let matchID = localStorage.setItem("matchID", e.target.id);
stats
.getFixture(e.target.id)
.then((fixtureData) => {
updateQuizMatchData(fixtureData);
})
.catch((err) => {
console.log(err);
});
document.location.href = "/quiz.html";
});
}
};
Originally, I did not store anything in localStorage, I just tried to call the function that makes an API call from the id directly. But the function doesn't seem to fire. it seems to break at setting the localStorage part. Is this because of the page load to a new page?
I stored the id in localStorage thinking that I could pull from that via another js file attached to the quiz.html page. As you can probably see, I am overcomplicating things maybe?
Anyhow, this is code above is meant to load the quiz.html page and then display the specific fixture related data from the fixture button that is clicked.
The code fires and updates localStorage and loads the quiz.html page. So I know it works to that point. But the other code does not fire. The other code that is meant to fire is an API call, followed then by this to update the quiz.html page dynamically...(not sure if this code is relevant to the issue I am seeing, as the API function call is not being fired either, which is why this below may not fire)
const updateQuizMatchData = (fixtureData) => {
console.log(fixtureData);
let date = "11-11-2001";
console.log(date);
teams.innerHTML = `
<div class="home-team m-4 pl-6">
<img
class="team-badge w-40 h-40"
src="${fixtureData.teams.home.logo}"
alt="home-team"
/>
<p
class="home-score text-center text-6xl m-6 bg-red-500 rounded-lg text-white p-6 shadow-xl"
>
${fixtureData.goals.home}
</p>
</div>
<div class="vs-text pt-20">
<p class="text-center text-6xl font-extrabold p-4">VS</p>
<p class="location text-center">${fixtureData.fixture.venue.name}</p>
<p class="date text-center">${date}</p>
</div>
<!-- Away team detail section -->
<div class="away-team m-4 pr-6">
<img
class="team-badge w-40 h-40"
src="${fixtureData.teams.away.logo}"
alt="away-team"
/>
<p
class="away-score text-center text-6xl m-6 bg-lime-500 rounded-lg text-white p-6 shadow-xl"
>
${fixtureData.goals.away}
</p>
</div>
`;
};
I know this doesnt fire because the console does not log the data at the top. All that happens is my quiz.html page loads my dummy content.
I have been battling this for a while and getting frustrated. What am I missing? Or not doing correctly?
I have tried moving code onto a separate js file but this has no impact. I also have attempted to fire the above function via window.load, but this doesn't fire it either. The introduction of localStorage was also to see if I could just fire a function from page load using localStorage ID that I set from button click as the parameter in the API call I make to get the specific fixture data. I hope this makes sense.
What am I missing?
How can I update the quiz.html from a specific fixture button that is clicked?

How to make a responsive grid for my Sanity blog that is dynamically generated based on time

I'm trying to make a blog that is dynamically generated using Sanity for the backend and React / JS for the front end I ran into a problem when I wanted to create a grid layout which needed to display only the latest three blog articles.
The Grid layout that I want is this:
But I can't seem to figure out how to make it work.
This is the code that I've made and in this code I mapped over the sanity backend and tried to display it in a grid. It displayed the right layout but I don't know hot to make the first two images small and the third bigger.
<div>
<h1 className="text-2xl">Most Recent Posts</h1>
<div className="underline"></div>
<div className="grid overflow-hidden grid-cols-2 grid-rows-2 gap-4 mt-6">
{allPostsData &&
allPostsData.map((post, index) => (
<div key={index} className="box">
<Link to={"/" + post.slug.current} key={post.slug.current}>
<img src={post.mainImage.asset.url} alt="" />
</Link>
<p className="text-gray-400 text-sm">PROGRAMING</p>
<h2 className="text-xl">{post.title}</h2>
</div>
))}
</div>
</div>

Append component to end of <p>

I'm trying to create a simple page footer in React and TailwindCSS where there is an emoji which shows a tooltip on hover. It looks great when the page is in desktop scaling, however when I test mobile scaling, the emoji doesn't stay appended to the end of the text, it is instead placed next to the whole component and reads as if it is in the middle of the text. Please see images below.
Does anyone know how I can essentially 'glue' this <Tooltip> component to the end of the <p> component?
The Tooltip component I am trying to use is from the Flowbite-React module: https://github.com/themesberg/flowbite-react/tree/main/src/lib/components/Tooltip
My code:
export default function Footer() {
return (
<div className="flex justify-center">
<div className="w-4/6">
....
<div className="flex w-full justify-center">
<p className="dark:text-gray-300 text-black mr-1">© Me test test test, 2022 - Built with ❤️ - Powered by</p>
<Tooltip content="Tooltip text">☕</Tooltip>
</div>
</div>
</div>
);
}
Desktop scaling:
Mobile scaling:
Thanks!
I've been unable to figure this out, so to work around it, I have duplicated the code, and reformatted one of the copies to display as I intended. One copy shows when the screen is 'small' or larger, and the newly formatted duplicate will show only on mobile devices.
<div className="w-full justify-center hidden sm:flex">
<p className="dark:text-gray-300 text-black mr-1 flex-0">© Me test test test, 2022 - Built with ❤️ - Powered by</p>
<Tooltip content="Tooltip text">☕</Tooltip>
</div>
<div className="w-full justify-center sm:hidden">
<p className="dark:text-gray-300 text-black mr-1 flex-0">© Me test test test, 2022 - Built with ❤️</p>
<div className="flex">
<p className="dark:text-gray-300 text-black mr-1 flex-0">Powered by</p>
<Tooltip content="Tooltip text">☕</Tooltip>
</div>
</div>
Result:

Scrollheight is not accurate for Nuxt app?

I have a very long (height) webpage and I'm using Puppeteer to get a PDF export of the page. It's about 30,000 px long.
I'm using document.documentElement.scrollHeight to try to determine dynamically the total height but it is returning 1018 when console.log and the PDF export is showing the same.
The 1018 is the viewport height so if I change the window it changes also.
Curious why this is?
The height is returning this way even in direct inspect > console.log and not using Puppeteer.
Any ideas why the height is not correct or how to fix this?
UPDATE:
This is my layout in nuxt
<template>
<div
id="my-app"
ref="layout"
class="flex flex-col h-screen overflow-hidden bg-gray-100 font-museo-sans"
>
<main class="overflow-y-auto">
<div class="max-w-7xl mx-auto py-5 xl:rounded-lg xl:shadow-md">
<Nuxt class="transition-opacity duration-200" />
</div>
</main>
</div>
</template>
The overflow-hidden and h-screen for some reason is necessary for my-app as if I remove it, the page does not allow for scroll.
I'm not quite understanding the behavior of this though. Why would overflow-hidden and setting a height to viewport allow the scrolling of the nuxt application?
In addition, I thought documentElement.scrollHeight returns overflow hidden but I guess it does not.

react-responsive-carousel is not displaying properly

I am working on an online ecommerce website using react js. On the details page for every product, I am using react-responsive-carousel to allow the user to slide through all images for that specific product. I also wanted there to be thumbnails underneath that are also selectable. react-responsive-carousel was a perfect choice because it was easy to implement and the look/functionality was almost exactly how I wanted it to look. Initially, everything was working fine, but for some reason the carousel stopped displaying properly. My code involving the carousel is the same as it was before, so I'm not sure what the issue is.
This is how the images are displaying now:
Top view of the carousel
Lower view of the carousel
As you can see, the images are stacked on top of each other, as well as the thumbnails. The next/previous buttons are in the wrong spot and each image is prepended with a bullet point.
This is my code for the entire product details page:
import React, { Component } from 'react';
import {ProductConsumer} from '../context.js';
import {Link} from 'react-router-dom';
import SizeSelector from './SizeSelector.js';
import {Carousel} from 'react-responsive-carousel';
export default class Details extends Component {
render() {
return (
<ProductConsumer>
{value => {
const {id, title, img, info, price, size} = value.detailProduct;
const images = img.map(index =>
<div>
<img className="img-fluid" key={id} src={index} alt="Product"/>
</div>
);
return (
<div className="mx-2 pb-5">
<div className="row">
<div className="col-10 mx-auto text-center my-5">
<h1>{title}</h1>
</div>
</div>
<div className="row">
<div className="col-10 mx-auto col-md-6 mb-3">
<Carousel>{images}</Carousel>
</div>
<div className="col-10 mx-auto col-md-6 mb-3">
<h3 className="mb-2">${price}</h3>
<p className="mb-5">{info}</p>
<SizeSelector />
<Link to="/products">
<button className="btn btn-black mr-5">Back to products</button>
</Link>
<span className="btn btn-black"
onClick={() => {
if (value.size === "")
{
value.openSizePrompt();
}
else
{
value.addToCart(id, value.size);
value.openModal(id, value.size);
}
}}>
Add to cart
</span>
</div>
</div>
</div>
)
}}
</ProductConsumer>
)
}
}
Also, I have a javascript file containing the product data. When a storeProduct is selected, the values of the product are set to a detailProduct. From there, I can get all of the data about that product. 'img' is the object containing the array of images. Each product may have a different amount of images (usually 2-4), so I have to dynamically create the <div> <img/> </div> using the img.map function.
If anyone has a clue on how to fix this issue, I would greatly appreciate the help. I really do not want to go through the effort of implementing my own carousel. I am more than happy to provide other information that may help fix the problem.
I solved the problem with a simple import:
import 'react-responsive-carousel/lib/styles/carousel.min.css'
However, before I ran into this issue, everything was displaying fine without this import. I am not sure what changed that required me to do this.

Categories

Resources