file rerendering on save - reactjs

import React, { useEffect, useState } from "react";
import styled from "styled-components";
import arcade from "../assets/images/icon-arcade.svg";
import advanced from "../assets/images/icon-advanced.svg";
import pro from "../assets/images/icon-pro.svg";
const SelectYourPlan = () => {
const [toggle, setToggle] = useState(0);
const [init, setInit] = useState(true);
useEffect(() => {
console.log(toggle);
console.log(init);
if (toggle === 0) {
document.getElementsByClassName("ball")[0].style.marginLeft = "0vw";
document.getElementById("left").style.color = "hsl(213, 96%, 18%)";
document.getElementById("right").style.color = "hsl(231, 11%, 63%)";
if (init === false) {
let arcade = document.getElementsByClassName("arcade")[0];
let advanced = document.getElementsByClassName("advanced")[0];
let pro = document.getElementsByClassName("pro")[0];
let arcadePrice = document.getElementById("arcadePrice");
let advancedPrice = document.getElementById("advancedPrice");
let proPrice = document.getElementById("proPrice");
arcadePrice.textContent = "$9/month";
advancedPrice.textContent = "$12/month";
proPrice.textContent = "$15/month";
arcade.removeChild(arcade.lastElementChild);
advanced.removeChild(advanced.lastElementChild);
pro.removeChild(pro.lastElementChild);
}
} else {
let extraContentElement = document.createElement("p");
extraContentElement.textContent = "2 months free";
let arcade = document.getElementsByClassName("arcade")[0];
let advanced = document.getElementsByClassName("advanced")[0];
let pro = document.getElementsByClassName("pro")[0];
let arcadePrice = document.getElementById("arcadePrice");
let advancedPrice = document.getElementById("advancedPrice");
let proPrice = document.getElementById("proPrice");
arcadePrice.textContent = "$90/year";
advancedPrice.textContent = "$120/year";
proPrice.textContent = "$150/year";
arcade.appendChild(extraContentElement.cloneNode(true));
advanced.appendChild(extraContentElement.cloneNode(true));
pro.appendChild(extraContentElement.cloneNode(true));
arcade.lastElementChild.id = "arcade-free";
advanced.lastElementChild.id = "advanced-free";
pro.lastElementChild.id = "pro-free";
document.getElementsByClassName("ball")[0].style.marginLeft = "1vw";
document.getElementById("right").style.color = "hsl(213, 96%, 18%)";
document.getElementById("left").style.color = "hsl(231, 11%, 63%)";
}
}, [toggle]);
const handleClick = () => {
if (toggle === 0) {
setToggle(1);
setInit(false);
} else {
setToggle(0);
}
};
return (
<Container>
<h1> Select your plan</h1>
<Subtitle>You have the option of monthly or yearly billing.</Subtitle>
<Flex>
<Arcade imgUrl={arcade} className="arcade">
<Title>Arcade</Title> <Price id="arcadePrice">$9/mo</Price>
</Arcade>
<Advanced imgUrl={advanced} className="advanced">
<Title>Advanced</Title>
<Price id="advancedPrice">$12/mo</Price>
</Advanced>
<Pro imgUrl={pro} className="pro">
<Title>Pro</Title>
<Price id="proPrice">$15/mo</Price>
</Pro>
</Flex>
<SwitchBar>
<Left id="left">Monthly</Left>
<Switch onClick={handleClick}>
<Ball className="ball"></Ball>
</Switch>
<Right id="right">Yearly</Right>
</SwitchBar>
<GoBack>Go Back</GoBack>
<Next>Next Step</Next>
</Container>
);
};
Actually I have a toggle switch whenever I click on that (when toggle state becomes 1) I want a extra sentence to display at the last in each of 'arcade','advanced','pro' components. This works fine but when I make some changes and save the file on the same toggle position (toggle=1) the statements keep on adding. If I do this on toggle=0 they start to get deleted as per the code. Maybe this is because the page re-renders on saving but is there any way to stop this as this poses great problem in debugging.

You seem to completely misunderstand the way React is meant to be used. You should not use id, class, or any of getElementsByClassName, getElementById, style, textContent, removeChild, createElement, cloneNode, etc.
Instead you should simply return something different depending on the current state and let React deal with DOM manipulation. Here is a cleaned up version of your code.
Note that we're simply returning different things depending on whether showYearly is true or false.
I renamed toggle to showYearly for clarity and removed init as I have no idea what it's meant to do.
import React, { useEffect, useState } from "react";
import styled from "styled-components";
import arcade from "../assets/images/icon-arcade.svg";
import advanced from "../assets/images/icon-advanced.svg";
import pro from "../assets/images/icon-pro.svg";
const SelectYourPlan = () => {
const [showYearly, setShowYearly] = useState(false);
const handleClick = () => {
setShowYearly(showYearly => !showYearly);
};
return (
<Container>
<h1> Select your plan</h1>
<Subtitle>You have the option of monthly or yearly billing.</Subtitle>
<Flex>
<Arcade imgUrl={arcade}>
<Title>Arcade</Title>
<Price>{showYearly ? "$90/year" : "$9/mo"}</Price>
{showYearly && <p>2 months free</p>}
</Arcade>
<Advanced imgUrl={advanced}>
<Title>Advanced</Title>
<Price>{showYearly ? "$120/year" : "$12/mo"}</Price>
{showYearly && <p>2 months free</p>}
</Advanced>
<Pro imgUrl={pro}>
<Title>Pro</Title>
<Price>{showYearly ? "$150/year" : "$15/mo"}</Price>
{showYearly && <p>2 months free</p>}
</Pro>
</Flex>
<SwitchBar>
<Left $showYearly={showYearly}>Monthly</Left>
<Switch onClick={handleClick}>
<Ball $showYearly={showYearly}/>
</Switch>
<Right $showYearly={showYearly}>Yearly</Right>
</SwitchBar>
<GoBack>Go Back</GoBack>
<Next>Next Step</Next>
</Container>
);
};
For the style on Left, Right and Ball, you should use transient props from styled-components. For instance:
const Left = styled.div`
color: ${props => props.$showYearly ? "hsl(213, 96%, 18%)" : "hsl(231, 11%, 63%)"};
[...]
`;

You can use React's state management keeping track of added elements and only add/remove as needed when toggle changes.
Something like this as reference, do adapt to your code, this is only an example.
const [addedElements, setAddedElements] = useState([]);
useEffect(() => {
if (toggle === 0) {
document.getElementsByClassName("ball")[0].style.marginLeft = "0vw";
document.getElementById("left").style.color = "hsl(213, 96%, 18%)";
document.getElementById("right").style.color = "hsl(231, 11%, 63%)";
if (init === false) {
let arcade = document.getElementsByClassName("arcade")[0];
let advanced = document.getElementsByClassName("advanced")[0];
let pro = document.getElementsByClassName("pro")[0];
let arcadePrice = document.getElementById("arcadePrice");
let advancedPrice = document.getElementById("advancedPrice");
let proPrice = document.getElementById("proPrice");
arcadePrice.textContent = "$9/month";
advancedPrice.textContent = "$12/month";
proPrice.textContent = "$15/month";
// Only remove elements if they were added before
if (addedElements.includes("arcade-free")) {
arcade.removeChild(document.getElementById("arcade-free"));
}
if (addedElements.includes("advanced-free")) {
advanced.removeChild(document.getElementById("advanced-free"));
}
if (addedElements.includes("pro-free")) {
pro.removeChild(document.getElementById("pro-free"));
}
}
} else {
let extraContentElement = document.createElement("p");
extraContentElement.textContent = "2 months free";
let arcade = document.getElementsByClassName("arcade")[0];
let advanced = document.getElementsByClassName("advanced")[0];
let pro = document.getElementsByClassName("pro")[0];
let arcadePrice = document.getElementById("arcadePrice");
let advancedPrice = document.getElementById("advancedPrice");
let proPrice = document.getElementById("proPrice");
arcadePrice.textContent = "$90/year";
advancedPrice.textContent = "$120/year";
proPrice.textContent = "$150/year";
// Only add elements if they haven't been added before
if (!addedElements.includes("arcade-free")) {
arcade.appendChild(extraContentElement.cloneNode(true));
arcade.lastElementChild.id = "arcade-free";
setAddedElements(prevAddedElements => [...prevAddedElements, "arcade-free"]);
}
if (!addedElements.includes("advanced-free")) {
advanced.appendChild(extraContentElement.cloneNode(true));
advanced.lastElementChild.id = "advanced-free";
Edit: Since this is not how you should be using React, here is an example of how to properly use React state to store the prices and render them
const [prices, setPrices] = useState({
arcade: "$9/month",
advanced: "$12/month",
pro: "$15/month"
});
useEffect(() => {
if (toggle === 1) {
setPrices({
arcade: "$90/year",
advanced: "$120/year",
pro: "$150/year"
});
} else {
setPrices({
arcade: "$9/month",
advanced: "$12/month",
pro: "$15/month"
});
}
}, [toggle]);
...
<Arcade imgUrl={arcade} className="arcade">
<Title>Arcade</Title>
<Price>{prices.arcade}</Price>
</Arcade>
<Advanced imgUrl={advanced} className="advanced">
<Title>Advanced</Title>
<Price>{prices.advanced}</Price>
</Advanced>
<Pro imgUrl={pro} className="pro">
<Title>Pro</Title>
<Price>{prices.pro}</Price>
</Pro>

Related

React counter not changing on the right interval

I am doing a small project with react lifecycles and I am attempting to change all box colors randomly every time the counter reaches a number divisible by 5 however, the boxes only change when the number is divisible by 10.
App.js:
import React from 'react';
import './App.css';
import Counter from "./components/Counter";
import Box from "./components/Box";
function App() {
const randomColor = [
"#0d0d8c",
"#a41313",
"#064826",
"#996e00"
];
const [number, setNumber] = React.useState(0);
const [boxes, setBoxes] = React.useState([]);
const [color, setColor] = React.useState('red');
const [change, setChange] = React.useState(false);
let box = boxes.map((obj, idx) =>
<Box key={idx} color={color} />
);
let getColor = () => {
if (boxes.length % 5 === 0) {
let rand = Math.floor(Math.random() * randomColor.length);
setColor(randomColor[rand]);
return randomColor[rand];
}
return color;
};
React.useEffect(() => {
if (boxes.length % 5 === 0) {
let rand = Math.floor(Math.random() * randomColor.length);
setColor(randomColor[rand]);
return randomColor[rand];
}
return color;
}, [color])
React.useEffect(() => {
if (number % 2 === 0) {
let newBoxList = [...boxes];
newBoxList.push({color: getColor()});
setBoxes(newBoxList);
}
}, [number,change]);
let reset = () => {
setNumber(0);
setBoxes([]);
setChange(true);
};
return (
<div className="App">
<button onClick={() => setNumber(number + 1)}>Increase</button>
<button onClick={reset}>reset</button>
<Counter count={number}/>
<div className="boxes">{box}</div>
</div>
);
}
export default App;
deployed site: https://priceless-spence-9ae99a.netlify.app/
I think the culprit is your useEffect() hook listening to number. Whenever number is even you are copying the existing contents of boxes and then adding new boxes to the existing boxes; you are not actually updating all boxes in the array. It seems your desire is to have all of those boxes, existing and new, be updated to a new color so you'll need to iterate through the array and update each.
I think it comes down to the fact that you are assigning the return value of getColor to your new boxes rather than the value of local state color.

Updating array context state in component updates strangely

I have a brand filter toggle that when it is triggered it adds or deletes a element to a brand's array and then in my context when i detect that the brand's array changed i make a second api call to add the brand filters to my api call.
And the moment when i update my state for the first time it works perfectly, the array updates and adds a new brand to the stack, but when i add a second one while looking at the components tab in developer's mode the state doesn't update but when i close developers tool's and open them again it appears as the delete or aggregation to the state worked, but the useEffect isn't triggered.
Empty state at first:
Working state when i click on the checkbox for the first time:
Not working at first when i update for the second time:
State updates when i close and open developers tools, but the useEffect isn't triggered adding a new parameter to the url:
If i check and then uncheck one box it updates correctly.
I don't really know why is this happening, if it's the context's state not updating properly or my component state not updating properly, it might be the component state not working but it is really weird that it updates after closing and opening and when i console log it it appears as updated.
Here is my sidebar component:
import "../App.css";
import React, { useContext } from "react";
import { ProductContext } from "../context/productContext";
const Sidebar = () => {
const { products, setProducts, brandFilter, setBrandFilter } =
useContext(ProductContext);
var brandsArray = [];
brandsArray.push(products[0].company);
for (var i = 1; i < products.length; i++) {
var isEqual = false;
for (var x = 0; x < brandsArray.length; x++) {
if (products[i].company == brandsArray[x]) {
isEqual = true;
}
}
if (isEqual == false) {
brandsArray.push(products[i].company);
}
}
const handleClick = (e) => {
var arrayFilters = [];
var isEqual = -1;
if (brandFilter.length > 0) {
arrayFilters = brandFilter;
}
for (var i = 0; i < arrayFilters.length; i++) {
if (e.target.value == arrayFilters[i]) {
isEqual = i;
}
}
if (isEqual == -1) {
arrayFilters.push(e.target.value);
} else {
arrayFilters.splice(isEqual, 1);
}
setBrandFilter(arrayFilters);
};
return (
<div className="sidebar p-2">
<div className="heading d-flex justify-content-between align-items-center">
<h6 className="text-uppercase">Brands</h6>
</div>
{brandsArray.map((brand) => (
<div className="d-flex justify-content-between mt-2">
<div className="form-check">
<input
className="form-check-input"
type="checkbox"
value={brand}
id="flexCheckDefault"
onClick={handleClick}
></input>
<label className="form-check-label"> {brand} </label>
</div>
</div>
))}
</div>
);
};
export default Sidebar;
And here is the context:
import React, { useState, createContext, useEffect } from "react";
export const ProductContext = createContext();
export const ProductProvider = (props) => {
var url = "/api/v1/products?";
const [productList, setProductList] = useState([]);
const [products, setProducts] = useState([]);
const [brandFilter, setBrandFilter] = useState([]);
const getProductList = async () => {
const response = await fetch(url);
const responseJson = await response.json();
if (responseJson) {
setProductList(responseJson.products);
}
};
const getProducts = async () => {
const response = await fetch("/api/v1/products?all=true");
const responseJson = await response.json();
if (responseJson) {
setProducts(responseJson.products);
}
};
useEffect(() => {
getProductList();
getProducts();
}, []);
useEffect(() => {
console.log("Something changed");
changeUrl();
getProductList();
}, [brandFilter]);
const changeUrl = () => {
if (brandFilter.length > 0) {
for (var i = 0; i < brandFilter.length; i++) {
url += `company=${brandFilter[i]}&`;
}
}
};
return (
<ProductContext.Provider
value={{
productList,
setProductList,
products,
setProducts,
brandFilter,
setBrandFilter,
}}
>
{props.children}
</ProductContext.Provider>
);
};
export default ProductProvider;

React - deleting items from array not rendering correctly. Wrong items remain displayed

I've created a simple react todo app, but I'm having an issue when deleting todo items in that they are remove from the array correctly being rendered incorrectly.
Example:
create 4 to do items; "one", "two", "three" "four"
select "one", "two" and delete these
the array returns "three" and "four" as expected however "one" and "two" still appear
this is the same for any number of selections in any order. The number selected always renders the first in the list i.e. don't delete 4 random out of 10 items and the first 4 items still remain in the list even if selected to remove.
the only scenario I can get to work is to select all and all delete as expected
I've seen some similar issues where people didn't have an id/index but I have this in place.
I use context to update the to do tasks, Tasks component to list all tasks and have Task component for each individual task.
When I console log the tasks from each of these they all return the correct result therefore I can't figure out how to fix the correct rendering.
Link to the react-app: https://dan-mca.github.io/todo-app/
The below are the main files but all files can are on https://github.com/dan-mca/todo-app/
Any help/pointers would be greatly appreciated. Thanks!
TasProvider.js
import React, {createContext, useState} from 'react';
export const TaskContext = createContext([])
const TaskProvider = (props) => {
const [tasks, setTasks] = useState([])
const [checkedTasks, setCheckedTasks] = useState([])
const addCheckedTask = task => setCheckedTasks([...checkedTasks, task])
const removeUncheckedTask = task => {
const index = checkedTasks.findIndex(el => el.id === task.id)
const checkedTasksCopy = [...checkedTasks]
checkedTasksCopy.splice(index,1)
setCheckedTasks(checkedTasksCopy)
}
const deleteTasks = (e) => {
if(e.target.innerText === 'Delete' || e.target.id === 'Delete') {
const filteredList = [...tasks].filter(task1 => ![...checkedTasks].find(task2 => task1.id === task2.id))
setTasks(filteredList)
}
}
const addTask = (task) => setTasks([...tasks, {id: tasks.length, taskText: task.taskText }])
console.log(tasks)
const data = {
tasks,
setTasks,
addCheckedTask,
removeUncheckedTask,
checkedTasks,
deleteTasks,
addTask
}
return (
<TaskContext.Provider value={data}>
{props.children}
</TaskContext.Provider>
)
}
export default TaskProvider;
Tasks.jsx
import React, { useContext, useState } from 'react'
import { TaskContext } from '../../context/TasksProvider';
import Task from '../Task/Task'
import { TasksContainer, TasksHeader, TasksParagraph, TasksList } from './Tasks.styled'
const Tasks = () => {
const taskContext = useContext(TaskContext)
console.log(taskContext.tasks)
return (
<TasksContainer >
<TasksHeader>Tasks</TasksHeader>
{ taskContext.tasks.length === 0 ?
<TasksParagraph>All tasks have been completed. Great job!</TasksParagraph>
:
<>
<TasksList >
{ taskContext.tasks.map((task) => (
<Task task={task} />
))
}
</TasksList>
<TasksParagraph>Tasks to complete: {taskContext.tasks.length}</TasksParagraph>
</>
}
</TasksContainer>
)
}
export default Tasks
Task.jsx
import React, { useState, useContext } from "react";
import { TaskContext } from "../../context/TasksProvider";
import { TaskItem, TaskEditIcon, TaskInput, TaskInputContainer, TaskInputLabel, TaskInputCheckbox } from './Task.styled'
const Task = (props) => {
const {task} = props;
const taskContext = useContext(TaskContext)
const [isClicked, setIsClicked] = useState(false)
const [taskText, setTaskText] = useState(task.taskText)
const handleClick = () => setIsClicked(!isClicked);
const handleChange = (e) => setTaskText(e.target.value);
const handleCheckboxclick = (e) => {
if (e.target.checked === true) {
taskContext.addCheckedTask({id: task.id, taskText})
} else if (e.target.checked === false) {
taskContext.removeUncheckedTask({id: task.id, taskText})
}
}
console.log(task)
return (
<TaskItem key={task.id}>
<TaskInputContainer>
{
isClicked ?
<TaskInput type="input" defaultValue={taskText} onChange={handleChange} id={task.id} />
:
<>
<TaskInputCheckbox type="checkbox" id={task.id} onClick={handleCheckboxclick}/>
<TaskInputLabel htmlfor={task.id}>{taskText}</TaskInputLabel>
</>
}
</TaskInputContainer>
<TaskEditIcon icon="clarity:edit-line" onClick={handleClick}/>
</TaskItem>
);
};
export default Task;

Why is updating state not causing a re-render (updating state using drag and drop)?

I am making a card system that can swap cards using drag and drop. When I'm dragging the cards over each other my state is updating as it's supposed to but it's not re-rendering.
import React, {useRef, useState} from 'react';
import DnDGroup from './DndGroup';
const DragNDrop = ({data}) => {
const [list, setList] = useState(data);
const dragItem = useRef();
const dragNode = useRef();
const getParams = (element) => {
const itemNum = element.toString();
const group = list.find(group => group.items.find(item => item === itemNum))
const groupIndex = list.indexOf(group);
const itemIndex = group.items.indexOf(itemNum);
return {'groupIndex': groupIndex, 'itemIndex': itemIndex}
}
const handleDragstart = (e) => {
dragNode.current = e.target;
setTimeout(() => {
dragNode.current.classList.add('current')
}, 0)
dragItem.current = getParams(e.target.value);
dragNode.current.addEventListener('dragend', () => {
if(dragNode.current !== undefined) {
dragNode.current.classList.remove('current')
}
})
}
const handleDragEnter = e => {
if(dragNode.current !== e.target && e.target.value !== undefined) {
const node = getParams(e.target.value);
const currentItem = dragItem.current;
[data[currentItem.groupIndex].items[currentItem.itemIndex], data[node.groupIndex].items[node.itemIndex]] = [data[node.groupIndex].items[node.itemIndex], data[currentItem.groupIndex].items[currentItem.itemIndex]];
setList(data);
console.log(list)
}
}
return (
<div className='drag-n-drop'>
{list.map(group => (
<DnDGroup
key={group.title}
group={group}
handleDragstart={handleDragstart}
handleDragEnter={handleDragEnter}
/>
))}
</div>
);
};
export default DragNDrop;
I also tried to do this:
setList([...data])
Using this it renders according to the state changes and works great inside one group, but when I want to drag a card to the other group, the state constantly changes back and forth like crazy, it also gives tons of console.logs.
How can I fix this?
With this line:
[data[currentItem.groupIndex].items[currentItem.itemIndex], data[node.groupIndex].items[node.itemIndex]] = [data[node.groupIndex].items[node.itemIndex], data[currentItem.groupIndex].items[currentItem.itemIndex]];
you're mutating a deeply nested object inside the data array. Never mutate state in React; it can result in components not re-rendering when you expect them to, in addition to other unexpected (and undesirable) side-effects.
Another thing that looks like it's probably an unintentional bug is that you're changing the data (original state) instead of the stateful list array.
Change it to:
const itemA = list[node.groupIndex].items[node.itemIndex];
const itemB = list[currentItem.groupIndex].items[currentItem.itemIndex];
const newList = [...list];
newList[currentItem.groupIndex] = {
...newList[currentItem.groupIndex],
items: newList[currentItem.groupIndex].map(
(item, i) => i !== currentItem.itemIndex ? item : itemB
)
};
newList[node.groupIndex] = {
...newList[node.groupIndex],
items: newList[node.groupIndex].map(
(item, i) => i !== node.itemIndex ? item : itemA
)
};
setList(newList);
This avoids the mutation of the nested items subarray.

React rewriting class with hooks causes re-render loops

I am working on an image transition react component, where it waits to have img1 loaded and then on a user click loads the img2, but fades img1 smoothly.
Tried re-writing the application with hooks to set the states - but when this is applied it creates an re-render loop error.
Is it because we are always setting img1 as currentImgSrc initially?
const [imgSrcOne, setImgSrcOne] = useState(currentImgSrc)
errors in the if/else block? or is setting the useState in the return causing the bug
tried removing the if/else block to make the application functional
https://jsfiddle.net/b531L6ho/
import {
ImageTransition
} from './imageTransition/imageTranition'
const {
useState
} = React
interface ImageContainerProps {
layer: string
currentImgSrc: string
notifyOnError: (url: string) => void
updateLayerLoading: (hasLoaded: boolean) = void
}
export const ImageTransitionContainer: React.SFC < ImageContainerProps > = ({
currentImgSrc,
layer,
notifyOnError,
updateLayerLoading
}) => {
const [imgSrcOne, setImgSrcOne] = useState(currentImgSrc)
const [displayImgOne, setdisplayImgOne] = useState(true)
const [imgOneLoaded, setImgOneLoaded] = useState(false)
const [imgSrcTwo, setImgSrcTwo] = useState(currentImgSrc)
const [displayImgTwo, setdisplayImgTwo] = useState(true)
const [imgTwoLoaded, setImgTwoLoaded] = useState(false)
if (imgSrcOne && currentImgSrc !== imgSrcOne) {
console.log("in the if statement")
setImgSrcTwo(currentImgSrc)
setDisplayImgTwo(two)
}
if (currentImgSrc !== imgSrcOne) {
setImgSrcne(currentImgSrc)
}
if (!imgSrcOne && !imgSrcTwo) {
setImgSrcOne(currentImgSrc)
setDisplayImgOne(true)
} else if (imgSrcOne && currentImgSrc !== imgSrcOne) {
setImgSrcTwo(currentImgSrc)
setDisplayImgTwo(true)
} else if (imgSrcTwo && currentImgSrc !== imgSrcTwo) {
setImgSrcOne(currentImgSrc)
setDisplayImgOne(true)
}
console.log("state --", imgSrcOne, displayImgOne, imgOneLoaded, imgSrcTwo, displayImgTwo, imgTwoLoaded)
return (
<>
<ImageTransition
displayImg={displayImgOne}
imgLoaded={imgOneLoaded}
imgSrc={imgSrcOne}
onExit={() => {
setImgSrcOne(null)
setImgOneLoaded(false)
}}
onLoad={() => {
setImgOneLoaded(true)
setDisplayImgTwo(false)
}}
/>
<ImageTransition
displayImg={displayImgTwo}
imgLoaded={imgTwoLoaded}
imgSrc={imgSrcTwo}
onExit={() => {
setImgSrcTwo(null)
setImgTwoLoaded(false)
}}
onLoad={() => {
setImgTwoLoaded(true)
setDisplayImgOne(false)
}}
/>
</>
)
}

Resources