How to display an image for few seconds on load? - reactjs

I'm trying to display an opening screen image that will last 5 seconds once the app loads. I'm using setTimeout but it won't work. Does anyone have an idea?
import OpeningScreen from '../../../../../../assets/images/OPENING_SCREEN.png';
function ProgressComponent() {
const [isOpeningScreenVisible, setOpeningScreenVisible] = useState(true)
setTimeout(() => {
setOpeningScreenVisible(false);
}, 5000);
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
}}
>
{isOpeningScreenVisible && <img src={OpeningScreen} className="image" />}
</div>
);
}
export default ProgressComponent;```

Try changing the img src.
From
{isOpeningScreenVisible && <img src={OpeningScreen} className="image" />}
To this
{isOpeningScreenVisible && <img src={OpeningScreen.src} className="image" />}

I've tested your code and it works fine. try these:
check your image path and be sure it's correct.
check and see if there is any error in the console and fix all of them.
maybe the loading time is taking more time than 5000ms. try 10000ms for showing the image.

You can update your code to use native events so you don't have to re-invent the wheel.
What i would do:
import OpeningScreen from '../../../../../../assets/images/OPENING_SCREEN.png';
function ProgressComponent() {
return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
}}
>
<img
src={OpeningScreen}
alt="opening screen"
onLoad={e => {
console.log("init event")
setTimeout(() => (e.target as HTMLImageElement).remove(), 5000)
}}
/>
</div>
);
}
export default ProgressComponent;
Anyway, this isn't the best approach. The best you can do is to use css transitions to animate just an opening screen

function App() {
const [loading, setLoading] = useState(false);
document.onreadystatechange = function () {
if (document.readyState !== "complete") {
setLoading(true);
} else if (document.readyState === "complete") {
setTimeout(() => {
setLoading(false);
}, 5000);
}
};
return (
<div style={{ background: "black" }}>
{loading && (
<div id="loadingScreen">
<img src={OpeningScreen} className="image" />
</div>
)}
{!loading && (
<div className="App" id="app"></div>
</div>
Try this It should work as it is still working in one of my project
The Basic Idea is the <img src={openingScreen}/> will be on the screen untill the react build file is loaded to on the site.
Add the everything inside <div className="App" id="app"></div> once they are loaded the image will fade.

Related

I am using react-dropzone in react js project, can't display preview image in chrome while working fine in firefox

I am using react-dropzone in reactjs project, while uploading images the preview shows a broken link with a error "net::ERR_FILE_NOT_FOUND". it is working fine in firefox.
in there own site it is not working in chrome you can check here https://react-dropzone.js.org/#section-previews. please guide what should I do in this.
"I think this error is because URL.createObjectURL
import {useDropzone} from 'react-dropzone';
const thumbsContainer = {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 16
};
const thumb = {
display: 'inline-flex',
borderRadius: 2,
border: '1px solid #eaeaea',
marginBottom: 8,
marginRight: 8,
width: 100,
height: 100,
padding: 4,
boxSizing: 'border-box'
};
const thumbInner = {
display: 'flex',
minWidth: 0,
overflow: 'hidden'
};
const img = {
display: 'block',
width: 'auto',
height: '100%'
};
function Previews(props) {
const [files, setFiles] = useState([]);
const {getRootProps, getInputProps} = useDropzone({
accept: 'image/*',
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}
});
const thumbs = files.map(file => (
<div style={thumb} key={file.name}>
<div style={thumbInner}>
<img
src={file.preview}
style={img}
/>
</div>
</div>
));
useEffect(() => {
// Make sure to revoke the data uris to avoid memory leaks
files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
return (
<section className="container">
<div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
<aside style={thumbsContainer}>
{thumbs}
</aside>
</section>
);
}
<Previews />
add return before files like this return () => files.forEach(file => URL.revokeObjectURL(file.preview)); inside useEffect
Currently the useEffect is revoking all blob URLs when files state update but we want the blob URLs to be available until component unmount.
Just change the useEffect implementation to:
useEffect(() => {
// Make sure to revoke the data uris to avoid memory leaks
return () => files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
This will revoke the blob URLs on unmount and will allow you to see the previews when the component is mounted.

Sync scroll react. div block with main scroll on window

I want to synchronize a divs scroll with a body scroll.
I tried some examples with two divs but I couldn't manage fix it with the body scroll.
Sample code with two divs: https://codesandbox.io/s/react-custom-scroll-sync-of-2-divs-10xpi
My Code
https://codesandbox.io/s/funny-rain-ditbv
import "./styles.css";
import { useRef } from "react";
export default function App() {
const firstDivRef = useRef();
const secondDivRef = useRef();
const handleScrollFirst = (scroll) => {
secondDivRef.current.scrollTop = scroll.target.scrollTop;
};
const handleScrollSecond = (scroll) => {
firstDivRef.current.scrollTop = scroll.target.scrollTop;
};
return (
<div
className="App"
style={{
display: "flex",
}}
>
<div
onScroll={handleScrollFirst}
ref={firstDivRef}
style={{
height: "500px",
overflow: "scroll",
backgroundColor: "#FFDAB9",
position: "sticky",
top: "0px"
}}
>
<div style={{ height: 5000, width: 300 }}>
The first div (or it can be tbody of a table and etc.)
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
<div
onScroll={handleScrollSecond}
ref={secondDivRef}
style={{
height: "100%",
backgroundColor: "#EEE8AA"
}}
>
<div style={{ height: 5000, width: 200 }}>
The second div
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
</div>
);
}
It was easy to use different divs rather than using a div and window.
But finally managed to run it with a div and the body.
The trick is they block each other since they listen each others values.
import "./styles.css";
import { useEffect, useRef, useState } from "react";
export default function App() {
const firstDivRef = useRef();
const [scrollTop, setScrollTop] = useState(0);
const [disableBodyScroll, setDisableBodyScroll] = useState(false);
const handleScrollFirst = (scroll) => {
setScrollTop(scroll.target.scrollTop);
};
useEffect(() => {
if (firstDivRef.current && !disableBodyScroll) {
firstDivRef.current.scrollTop = scrollTop;
}
if (disableBodyScroll) {
window.scrollTo(0, scrollTop);
}
}, [firstDivRef, scrollTop, disableBodyScroll]);
useEffect(() => {
const onScroll = () => {
console.log(disableBodyScroll, window.scrollY);
if (!disableBodyScroll) {
setScrollTop(window.scrollY);
}
};
// clean up code
window.removeEventListener("scroll", onScroll);
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [disableBodyScroll]);
return (
<div
className="App"
style={{
display: "flex"
}}
>
<div
onMouseEnter={() => setDisableBodyScroll(true)}
onMouseLeave={() => setDisableBodyScroll(false)}
onScroll={handleScrollFirst}
ref={firstDivRef}
style={{
height: "500px",
overflow: "scroll",
backgroundColor: "#FFDAB9",
position: "sticky",
top: "0px"
}}
>
<div style={{ height: 5000, width: 300 }}>
The first div (or it can be tbody of a table and etc.)
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
<div
style={{
height: "100%",
backgroundColor: "#EEE8AA"
}}
>
<div style={{ height: 5000, width: 200 }}>
The second div
{[...new Array(1000)].map((_, index) => {
const isEven = index % 2 === 0;
return (
<div style={{ backgroundColor: isEven ? "#FFFFE0 " : "#FFDAB9" }}>
{index}
</div>
);
})}
</div>
</div>
</div>
);
}
https://codesandbox.io/s/ancient-dream-tzuel?file=/src/App.js
Try the next example. This is a quick sketch but maybe it will help you.
https://codesandbox.io/s/gallant-goldwasser-19g4d?file=/src/App.js

Synchronize Scrolling over mapped React Components

I am trying to synchronize scrolling in my React page. As you can see, I have a div-container containing an arbitrary number of one Component, depending on the length of the array. I've tried react-scroll-sync and scroll-sync-react, but to no avail... Any ideas?
Edit: to be more precise, there is an iframe in each component that is the scrollable part.
<div>
{array.map((value, index) => (
<MyComponent style={{ overflow: 'auto' }} />
))}
</div>
I tried the following: Removing the Component and just producing arr.length-times iframes. But that also didn't work:
import "./styles.css";
// import { ScrollSync, ScrollSyncNode } from "scroll-sync-react";
import { ScrollSync, ScrollSyncPane } from "react-scroll-sync";
const arr = [1, 2, 3];
export default function App() {
return (
<ScrollSync>
<div
className="App"
style={{ display: "flex", height: "500px", width: "500px" }}
>
{arr.map((element, index) => (
<ScrollSyncPane key={arr[index]}>
<iframe
src={mySource}
key={arr[index]}
title={arr[index]}
styles={{ height: "300px", width: "200px", overflow: "auto" }}
/>
</ScrollSyncPane>
))}
</div>
</ScrollSync>
);
}

Is there any difference between using React.lazy suspense against using onLoad prop in a <img>?

I would like to know which are the benefits of using React Lazy and Supense against what I am showing you below. First Example is using useState and Onload Prop, and second example is using React Lazy and Suspense.
const ImageComponent = ({ src }) => {
const [load, setLoad] = useState(false);
//handles load of the image
const handleOnload = () => {
setLoad(true);
};
return (
<>
{!load && <Spinner>}
<img
src={src}
alt="Avatar"
onLoad={handleOnload}
style={{
height: '192px',
width: '50%',
display: load ? 'inline' : 'none',
}}
/>
</>
);
};
VS this
<Suspense
fallback={
<Spinner style={{ width: '50%' }} />
}
>
<ImageComponent src={listItem.download_url} />
</Suspense>
ImageComponent.js
const ImageComponent = ({ src }) => {
return (
<img
src={src}
alt="Avatar"
style={{
height: '192px',
width: '50%',
}}
/>
);
};
export default ImageComponent;

What is best way to do lazy loading in a Next js Application?

I checked the documentation about Lazy Loading components on the official next js docs page (https://nextjs.org/learn/excel/lazy-loading-components).
I tried the steps mentioned and it did not work for me. Below is the piece of code that I want to lazy-load:
<div id="cards" className={index.sectionCards} style={{paddingBottom: '0px'}}>
<div className="title" style={{marginBottom: "0px", paddingBottom: "0px"}}>
Take a Look at Our Exciting Range of Cards
</div>
{this.renderCards()}
<div></div>
</div>
Here the renderCards function makes a call to a backend API and gets images from AWS S3, this whole process takes a lot of time and hence increases the overall page load time, below is the code for the function renderCards:
renderCards() {
const keys = Object.keys(this.state.products);
const valid_keys = ['Specials', 'New Beginnings', 'Expressions', 'Celebrations' ];
if(keys.length == 0) return <div></div>
return (<div className={index.cards}>
{
keys.map((key) => {
if(valid_keys.indexOf(key) > -1) return <div style={{ width: '80%', margin: '0 auto' }}>
<div className={index.category}>{key}</div>
<div style={{ display: 'flex', overflow: 'scroll' }} >
{this.state.products[key].map((c) => {
if(c.status == 'PRODUCT_ACTIVE') {
return <img onClick={() => this.onClickProduct(c)} className={index.cardImage} src={`<backend URL here>`} />
}
})}
</div>
</div>
})
}
</div>)
}
The objective was to lazy load this component to improve the overall page speed.
If anyone knows a way to solve this problem, please share.
Documentation for dynamic/lazy loading with nextjs
const Cards = () => {
const renderCards = () => {
const keys = Object.keys(this.state.products);
const valid_keys = [
"Specials",
"New Beginnings",
"Expressions",
"Celebrations",
];
if (keys.length == 0) return <div></div>;
return (
<div className={index.cards}>
{keys.map((key) => (
<Fragment key={key}>
{valid_keys.indexOf(key) > -1 && (
<div style={{ width: "80%", margin: "0 auto" }}>
<div className={index.category}>{key}</div>
<div style={{ display: "flex", overflow: "scroll" }}>
{this.state.products[key].map((c) => (
<Fragment key={c.id}>
{c.status === "PRODUCT_ACTIVE" && (
<img
onClick={() => this.onClickProduct(c)}
className={index.cardImage}
src={`<backend URL here>`}
/>
)}
</Fragment>
))}
</div>
</div>
)}
</Fragment>
))}
</div>
);
};
return (
<div
id="cards"
className={index.sectionCards}
style={{ paddingBottom: "0px" }}
>
<div
className="title"
style={{
marginBottom: "0px",
paddingBottom: "0px",
}}
>
Take a Look at Our Exciting Range of Cards
<div>{this.renderCards()}</div>
</div>
</div>
);
};
```
above code is not my code but a replication of the code in the question.
```
```
from nextjs
For the best understanding of dynamic/lazy load see link provided.
import dynamic from "next/dynamic";
```
import LoadSpinner from "../loadSpinner";
const Cards = dynamic(() => import("./cards"), {
```
this can be a custom loader or a node_module installed or just <div>Loading...</div> the loading: function will display while waiting for the import fucntion to load.
loading: () => <LoadSpinner />,
```
});
const CardContainer = () => ( <Cards /> );

Resources