i am a beginner with react and im working on a little clickergame.
My problem is, that i want to use useState to automaticly increase the number (with setInterval) but i also want to increase the number with click on the button. The shown percentages are wild hopping because he shows me an early state and a later state at the same time.
function App() {
const [findWorkCount, setfindWorkCount] = useState(0);
setInterval(findWorkRunner, '500');
function findWorkRunner() {
setfindWorkCount(findWorkCount + 1);
if (findWorkCount >= 101) {
setfindWorkCount(0);
}
}
return (
<div className="App">
<button
onClick={() => {
setfindWorkCount(findWorkCount + 11);
}}
>
Find Job
</button>
<div className="bar">
<div className="fillwork" style={{ width: `${findWorkCount}%` }}>
<div className="counter">{findWorkCount}%</div>
</div>
</div>
</div>
);
}
When you use an interval in a function component you need to wrap in a useEffect block to ensure that it doesn't create an interval on each render. Since findWorkRunner is a dependency of the useEffect, you need to wrap it in useCallback. You should also use findWorkRunner for the button as well, so the same logic would apply to the button, and the interval updates.
Finally, use a function to update the state, because the updated state is computed using the previous state:
setfindWorkCount(count =>
count + inc >= 101 ? 0 : count + inc
);
Example:
const { useState, useCallback, useEffect } = React;
function App() {
const [findWorkCount, setfindWorkCount] = useState(0);
const findWorkRunner = useCallback((inc = 1) => {
setfindWorkCount(count =>
count + inc >= 101 ? 0 : count + inc
);
}, []);
useEffect(() => {
const interval = setInterval(findWorkRunner, '500');
return () => {
clearInterval(interval);
};
}, [findWorkRunner]);
return (
<div className="App">
<button
onClick={() => {
findWorkRunner(11);
}}
>
Find Job
</button>
<div className="bar">
<div className="fillwork" style={{ width: `${findWorkCount}%` }}>
<div className="counter">{findWorkCount}%</div>
</div>
</div>
</div>
);
}
ReactDOM
.createRoot(root)
.render(<App />);
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div id="root"></div>
You can fix the issue by using the callback form of setfindWorkCount in the setInterval to ensure the state update happens after the render:
function App() {
const [findWorkCount, setfindWorkCount] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setfindWorkCount(c => c + 1);
if (findWorkCount >= 101) {
setfindWorkCount(0);
}
}, 500);
return () => clearInterval(intervalId);
}, []);
return (
<div className="App">
<button
onClick={() => {
setfindWorkCount(c => c + 11);
}}
>
Find Job
</button>
<div className="bar">
<div className="fillwork" style={{ width: `${findWorkCount}%` }}>
<div className="counter">{findWorkCount}%</div>
</div>
</div>
</div>
);
}
Set up a setTimeout inside useEffect instead.
useEffect(() => {
const id = setTimeout(() => {
setfindWorkCount(findWorkCount + 1);
if (findWorkCount >= 100) setfindWorkCount(0);
}, 500);
return () => clearTimeout(id);
}, [findWorkCount]);
Related
NOTE: You can view and edit the code in CodeSandbox.
I have the following parent file which creates a useState list of child component called ProgressBar:
import React, { useState } from 'react';
import ProgressBar from './ProgressBar';
import './App.css';
var idCounter = 0;
export default function App() {
const [barsArray, setBarsArray] = useState([]);
const [input, setInput] = useState('');
function add() {
setBarsArray((prev) => [
...prev,
<ProgressBar key={idCounter++} restart={false} />,
]);
}
function remove() {
setBarsArray((prev) => prev.filter((bar) => bar.key !== input));
}
function reset() {
setBarsArray((prev) =>
prev.map((bar) => (bar.key === input ? { ...bar, restart: true } : bar))
);
}
return (
<div className='App'>
<div className='buttons'>
<button className='button-add' onClick={add}>
Add
</button>
<button className='button-delete' onClick={remove}>
Delete
</button>
<button className='button-delete' onClick={reset}>
Reset
</button>
<input
type='number'
value={input}
onInput={(e) => setInput(e.target.value)}
/>
</div>
<div className='bars-container'>
{barsArray.map((bar) => (
<div className='bars-index' key={bar.key}>
{bar}
<p>{bar.key}</p>
</div>
))}
</div>
</div>
);
}
The file of the child ProgressBar has the following content:
import React, { useEffect, useState } from 'react';
import './ProgressBar.css';
export default function ProgressBar(props) {
const [progress, setProgress] = useState(0);
let interval;
useEffect(() => {
interval = setInterval(() => {
setProgress((prev) => prev + 1);
}, RnadInt(10, 120));
}, []);
useEffect(() => {
if (progress >= 100) clearInterval(interval);
}, [progress]);
if (props.restart === true) {
setProgress(0);
}
return (
<>
<div className='ProgressBarContainer'>
<div className='ProgressBar' style={{ width: progress + '%' }}></div>
</div>
</>
);
}
function RnadInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
My problem is that the reset button in the parent doesn't work, as far as I'm concerned, if you change the passed props to the child, the child automatically re-renders, but even though I'm updating the props in reset function in the parent, which maps the old array of child components to a new array and only changes the props of the selected child.
Thanks!
Adding the element in state via add would require to keep the ref of element instead of actual prop bind to element. Suggestion here to use the model object and while rendering use the JSX element.
Please use the below code which defines the barsArray as object state and later uses it render ProgressBar component (from map call).
Check the working codesandbox - https://codesandbox.io/s/admiring-glitter-j3b7sw?file=/src/App.js:0-1446
import React, { useState } from "react";
import ProgressBar from "./ProgressBar";
import "./App.css";
var idCounter = 0;
export default function App() {
const [barsArray, setBarsArray] = useState([]);
const [input, setInput] = useState("");
function add() {
setBarsArray((prev) => [...prev, { id: idCounter++, restart: false }]);
}
function remove() {
setBarsArray((prev) =>
prev.filter((bar) => bar.id.toString() !== input.toString())
);
}
function reset() {
setBarsArray((prev) =>
prev.map((bar) => {
return bar.id.toString() === input.toString()
? { ...bar, restart: true }
: { ...bar };
})
);
}
return (
<div className="App">
<div className="buttons">
<button className="button-add" onClick={add}>
Add
</button>
<button className="button-delete" onClick={remove}>
Delete
</button>
<button className="button-delete" onClick={reset}>
Reset
</button>
<input
type="number"
value={input}
onInput={(e) => setInput(e.target.value)}
/>
</div>
<div className="bars-container">
{barsArray.map((bar) => (
<div className="bars-index" key={bar.id}>
<ProgressBar key={bar.id} restart={bar.restart} />
<p>{bar.key}</p>
</div>
))}
</div>
</div>
);
}
This simple fix worked for me, in the file of the child, call the conditional expression in a useEffect hook. Currently, it doesn't listen to the changes in props.restart and only runs on the initial render.
check https://reactjs.org/docs/hooks-reference.html#useeffect
useEffect(() => {
if (props.restart === true) {
setProgress(0);
}
}, [props.restart])
link to working codesandbox https://codesandbox.io/s/distracted-gauss-24d0pu
Happy 2k22! I am building a countdown timer. I have two files. The first file takes the countDown time from input and the second from select dropdown .
I have implemented an increment button in the first file. It increases the countDown time by inc seconds i.e. time = time + inc.
So what's peculiar?
Thing is that when inc is replaced with any constant value, it works properly.
<button onClick={() => setSecondsRemaining(secondsRemaining + 3)}>
Increment {inc} sec
</button>
But when I used the input to enter the value and supply it through the variable inc, then it does not work. It increases randomly.
<button onClick={() => setSecondsRemaining(secondsRemaining + inc)}>
Increment {inc} sec
</button>
You can visit InputCountDown.js here
This is the full code:
import React, { useState, useEffect, useRef } from "react";
import "./styles.css";
const STATUS = {
STARTED: "Started",
STOPPED: "Stopped"
};
export default function InputCountDown() {
const [time, setTime] = useState(0);
const [inc, setInc] = useState(0);
const handleOnChange = (e) => {
//console.log(e.target.value);
setTime(e.target.value);
};
const handleOnChangeIncrement = (e) => {
console.log(e.target.value);
setInc(e.target.value);
};
const [secondsRemaining, setSecondsRemaining] = useState(time * 60);
//console.log(time);
const [status, setStatus] = useState(STATUS.STOPPED);
const secondsToDisplay = secondsRemaining % 60;
const minutesRemaining = (secondsRemaining - secondsToDisplay) / 60;
const minutesToDisplay = minutesRemaining % 60;
const hoursToDisplay = (minutesRemaining - minutesToDisplay) / 60;
const handleStart = () => {
setStatus(STATUS.STARTED);
setSecondsRemaining(time * 60);
};
const handleStop = () => {
setStatus(STATUS.STOPPED);
};
const handleReset = () => {
setStatus(STATUS.STOPPED);
setSecondsRemaining(time * 60);
};
useInterval(
() => {
if (secondsRemaining > 0) {
setSecondsRemaining(secondsRemaining - 1);
} else {
setStatus(STATUS.STOPPED);
}
},
status === STATUS.STARTED ? 1000 : null
// passing null stops the interval
);
return (
<>
<div className="App">
<h1>Countdown Using Input</h1>
<div style={{ padding: "12px" }}>
<label htmlFor="time"> Enter time in minutes </label>
<input
type="text"
id="time"
name="time"
value={time}
onChange={(e) => handleOnChange(e)}
/>
</div>
<div style={{ padding: "12px" }}>
<label htmlFor="inc"> Enter increment </label>
<input
type="text"
id="inc"
name="inc"
value={inc}
onChange={(e) => handleOnChangeIncrement(e)}
/>
</div>
<button onClick={handleStart} type="button">
Start
</button>
<button onClick={handleStop} type="button">
Stop
</button>
<button onClick={handleReset} type="button">
Reset
</button>
<div style={{ padding: 20, fontSize: "40px" }}>
{twoDigits(hoursToDisplay)}:{twoDigits(minutesToDisplay)}:
{twoDigits(secondsToDisplay)}
<div>
<button onClick={() => setSecondsRemaining(secondsRemaining + inc)}>
Increment {inc} sec
</button>
</div>
</div>
<div>Status: {status}</div>
</div>
</>
);
}
// source: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
// https://stackoverflow.com/a/2998874/1673761
const twoDigits = (num) => String(num).padStart(2, "0");
You can visit InputCountDown.js here
Please help me.
It's a very basic rule you missed mate. Whenever you get anything from TextInput, its always a string, even if you entered an integer. Try this:
<button onClick={() => setSecondsRemaining(secondsRemaining + parseInt(inc))}>
Increment {inc} sec
</button>
When consuming values from input elements recall that these are always string type values. Best to maintain the number type state invariant, so do the conversion from string to number when updating state.
const handleOnChange = (e) => {
setTime(Number(e.target.value));
};
const handleOnChangeIncrement = (e) => {
setInc(Number(e.target.value));
};
To help ensure users are entering number-like data into the inputs, specify each input to be type="number".
<div style={{ padding: "12px" }}>
<label htmlFor="time"> Enter time in minutes </label>
<input
type="number" // <-- number type
id="time"
name="time"
value={time}
onChange={handleOnChange}
/>
</div>
<div style={{ padding: "12px" }}>
<label htmlFor="inc"> Enter increment </label>
<input
type="number" // <-- number type
id="inc"
name="inc"
value={inc}
onChange={handleOnChangeIncrement}
/>
</div>
Recall also that when enqueueing state updates that if the next state value depends on the previous state value, i.e. when incrementing counts, etc..., that you should use a functional state update.
<button onClick={() => setSecondsRemaining(time => time + inc)}>
Increment {inc} sec
</button>
Introduction
I am building the countdown timer, which I had built but now I want to scale it up. So I am building two countdowns on the same page with each of them having separate start, stop buttons, and common reset button.
What do I have?
I have implemented but they are not working independently. For example, when I click on the stop of the upper clock, it also stops the lower clock.
What do I want?
I wanted to have separate functions for both of them but on the same page.
Code
Most of the things are repeated in the code.
import React, { useState, useEffect, useRef } from "react";
import "./styles.css";
const STATUS = {
STARTED: "Started",
STOPPED: "Stopped"
};
const STATUSp1 = {
STARTED: "Started",
STOPPED: "Stopped"
};
export default function InputCountDown() {
const [time, setTime] = useState(0);
const [timep1, setTimep1] = useState(0);
const [inc, setInc] = useState(0);
const handleOnChange = (e) => {
//console.log(e.target.value);
setTime(e.target.value);
setTimep1(e.target.value);
};
const handleOnChangeIncrement = (e) => {
console.log(e.target.value);
setInc(e.target.value);
};
const [secondsRemaining, setSecondsRemaining] = useState(time * 60);
const [secondsRemainingp1, setSecondsRemainingp1] = useState(timep1 * 60);
//console.log(time);
const [status, setStatus] = useState(STATUS.STOPPED);
const [statusp1, setStatusp1] = useState(STATUSp1.STOPPED);
const secondsToDisplay = secondsRemaining % 60;
const minutesRemaining = (secondsRemaining - secondsToDisplay) / 60;
const minutesToDisplay = minutesRemaining % 60;
const hoursToDisplay = (minutesRemaining - minutesToDisplay) / 60;
const secondsToDisplayp1 = secondsRemainingp1 % 60;
const minutesRemainingp1 = (secondsRemainingp1 - secondsToDisplayp1) / 60;
const minutesToDisplayp1 = minutesRemainingp1 % 60;
const hoursToDisplayp1 = (minutesRemainingp1 - minutesToDisplayp1) / 60;
const handleStart = () => {
setStatus(STATUS.STARTED);
setSecondsRemaining(time * 60);
};
const handleStartp1 = () => {
setStatusp1(STATUSp1.STARTED);
setSecondsRemainingp1(timep1 * 60);
};
const handleStop = () => {
setStatus(STATUS.STOPPED);
};
const handleStopp1 = () => {
setStatusp1(STATUSp1.STOPPED);
};
const handleReset = () => {
setStatus(STATUS.STOPPED);
setSecondsRemaining(time * 60);
setSecondsRemainingp1(timep1 * 60);
};
useInterval(
() => {
if (secondsRemaining > 0) {
setSecondsRemaining(secondsRemaining - 1);
} else {
setStatus(STATUS.STOPPED);
}
if (secondsRemainingp1 > 0) {
setSecondsRemainingp1(secondsRemainingp1 - 1);
} else {
setStatusp1(STATUSp1.STOPPED);
}
},
status === STATUS.STARTED ? 1000 : null,
statusp1 === STATUSp1.STARTED ? 1000 : null
// passing null stops the interval
);
return (
<>
<div className="App">
<h1>Countdown Using Input</h1>
<div style={{ padding: "12px" }}>
<label htmlFor="time"> Enter time in minutes </label>
<input
type="text"
id="time"
name="time"
value={time}
onChange={(e) => handleOnChange(e)}
/>
</div>
<div style={{ padding: "12px" }}>
<label htmlFor="inc"> Enter increment </label>
<input
type="number"
id="inc"
name="inc"
value={inc}
onChange={(e) => handleOnChangeIncrement(e)}
/>
</div>
<button onClick={handleStart} type="button">
Start
</button>
<button onClick={handleStop} type="button">
Stop
</button>
<button onClick={handleReset} type="button">
Reset
</button>
<div>
<button
onClick={() =>
setSecondsRemaining(secondsRemaining + parseInt(inc, 10))
}
>
Increment {inc} sec
</button>
</div>
<div style={{ padding: 20, fontSize: "40px" }}>
{twoDigits(hoursToDisplay)}:{twoDigits(minutesToDisplay)}:
{twoDigits(secondsToDisplay)}
</div>
<div>Status: {status}</div>
<div style={{ padding: 20, fontSize: "40px" }}>
{twoDigits(hoursToDisplayp1)}:{twoDigits(minutesToDisplayp1)}:
{twoDigits(secondsToDisplayp1)}
</div>
<button onClick={handleStartp1} type="button">
Start_p1
</button>
<button onClick={handleStopp1} type="button">
Stop_p1
</button>
<button onClick={handleReset} type="button">
Reset_p1
</button>
</div>
</>
);
}
// source: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
// https://stackoverflow.com/a/2998874/1673761
const twoDigits = (num) => String(num).padStart(2, "0");
You can also find the code in the codesandbox in the inputCountDown.js file .
You can ignore increment button
Please help me !!!
You are using the same interval for two different counters, which causes them to sync up on the same time. Nevertheless, this code is handling too many responsibilities at once and contains unnecessary duplications that is polluting the readability of the code.
Instead of duplicating the same code with different variables names, try extracting it into its own component, and call that component twice. This way, more code isolation is ensured and is definitely less error prone, while improving readability.
Seperate the useInterval logic for each of the timer
useInterval(
() => {
if (secondsRemaining > 0) {
setSecondsRemaining(secondsRemaining - 1);
} else {
setStatus(STATUS.STOPPED);
}
},
status === STATUS.STARTED ? 1000 : null
);
useInterval(
() => {
if (secondsRemainingp1 > 0) {
setSecondsRemainingp1(secondsRemainingp1 - 1);
} else {
setStatusp1(STATUSp1.STOPPED);
}
},
statusp1 === STATUSp1.STARTED ? 1000 : null
// passing null stops the interval
);
I am doing my first real React app and I ran into a bug I can't seem to fix.
I have a card component somewhere in my app that, when it gets clicked it maximizes to take up a bigger section of the screen. It is called in MainSelectionButton.js as follows:
export default function MainSelectionButtons(props) {
const [maximizeCard, setMaximizeCard] = useState('nothing')
if (maximizeCard === 'nothing') {
return <ImageButton
title={props.title}
icon={props.icon}
whatIsMaximized={setMaximizeCard}
/>
}
else return <MaximizedPlot
title={maximizeCard}
whatIsMaximized={setMaximizeCard}
cryptoData={props.cryptoData}
daysChangeHandler={props.daysChangeHandler}
days={props.days}
/>
}
MaximizedPlot looks like this:
export default function MaximizedPlot(props) {
const sorter = (item) => {
switch (item) {
case 'Strategy Plot':
return strategyPlot;
case 'Value Plot':
return valuePlot
case 'Relative Plot':
return relativePlot;
default: break
}
}
const daysChangeHandler = (newDays) => {
props.daysChangeHandler(newDays)
}
const xButtonHandler = () => {
props.whatIsMaximized('nothing')
}
const title = (props.days === 0) ? 'the maximal number of days' : props.days
return <Card backgroundColor='#192734' isMaximized='maximized' >
<XButton onClick={() => xButtonHandler()}>x</XButton>
<h1>{props.title + ' over ' + title}</h1>
<img src={sorter(props.title)} width='100%' alt=''></img>
<NumberOfDays daysChangeHandler={daysChangeHandler}
cryptoData={props.cryptoData}>
</NumberOfDays>
</Card>
}
This component looks like this:
Maximized card component
With the XButton component on the top right corner and the NumberOfDays component being the input field at the bottom of the graph.
export default function App() {
const [cryptoData, setCryptoData] = useState({ timestamp: [], price: [], long_ma: [], short_ma: [], money: [], action: [] })
const [hours, setHours] = useState(744)
useEffect(() => {
getData(30 * 24).then(response => setCryptoData(response))
}, []);
const daysChangeHandler = (days) => {
setHours(days * 24, getData(hours).then(response => setCryptoData(response)))
console.log('days Changed!! new:', days)
}
return (
<div className="App">
<Card isMaximized=''>
<MainSelectionButtons title={'Strategy Plot'} icon={iconStrategy} cryptoData={cryptoData} daysChangeHandler={daysChangeHandler} days={hours / 24}></MainSelectionButtons>
<MainSelectionButtons title={'Value Plot'} icon={iconValue} cryptoData={cryptoData} daysChangeHandler={daysChangeHandler} days={hours / 24}></MainSelectionButtons>
<MainSelectionButtons title={'Relative Plot'} icon={iconRelative} cryptoData={cryptoData} daysChangeHandler={daysChangeHandler} days={hours / 24}></MainSelectionButtons>
</Card>
<Card>
is running
</Card>
</div>
);
}
EDIT: the user input component, called NumberOfDays looks like this:
export default function NumberOfDays(props) {
const [typedDays, setTypedDays] = useState(30)
const inputDaysChangeHandler = (event) => {
setTypedDays(event.target.value)
}
const submitHandler = () => {
props.daysChangeHandler(typedDays)
}
const predefinedDaysHandler = (days) => {
props.daysChangeHandler(days)
}
return <div>
<div className='input-form'>
Enter number of days to display:
<input type='number'
onChange={inputDaysChangeHandler}
className='days-number-input' />
<input
type='submit'
className='submit-button'
onClick={() => submitHandler()} />
or:
<button className='submit-button' onClick={() => predefinedDaysHandler(0)}>Max</button>
<button className='submit-button' onClick={() => predefinedDaysHandler(30)}>30 days</button>
<button className='submit-button' onClick={() => predefinedDaysHandler(240)} >10 days</button>
</div>
</div>
}
THE PROBLEM
Whenever I click on a button in the user input field (so 'submit', 'max', etc.) the window gets minimized. I can't figure out why, it just closes every time. What am I doing wrong? Is there something fundamentally wrong with my code or is it a little logical mistake that I am missing?
Thank you in advance for the help, I spent already more time on it than I'd like to admit.
UPDATE:
If anyone has this problem, It is solved if instead of using props, you use context.
I am making a game like application where from Game.js file i am passing object to child GameIntro.js file every 3 seconds but it seems i am unable to do it through below code.
My intention is that every 3 seconds different objects should pass to child component and remove the previous passed component.
Game.js file::
import React from 'react';
import {gdatas} from './gamedata';
import GameIntro from './GameIntro';
const Game = () => {
// const [item, setItem] = useState();
return (
<div>
{gdatas && gdatas.map((gdata,i) => {
return setInterval(() => (
<GameIntro key={i} gdata={gdata} />
),2000)
}
)}
</div>
)
}
export default Game;
GameIntro.js file
import React from 'react';
// import {gdatas} from './gamedata';
const GameIntro = ({gdata}) => {
const gameData = gdata.data.map((elm,i) => {
return (
<div className="col-md-6" key={i}>
<div className="card">
<img src={elm.image} className="card-img-top img-fluid"
alt={elm.word} style={{'width' : '350px' , 'height' : '350px'}} />
<div className="card-body">
<h5 className="card-title mt-3">{elm.word}</h5>
</div>
</div>
</div>
)
})
return (
<div className="row">
{gameData }
</div>
)
}
export default GameIntro;
setInterval returns an id. It doesn't make sense to return it as part of .map. You can use setState and start the interval once (here I'm simulating an interval with setTimeout):
import React from 'react';
import {gdatas} from './gamedata';
import GameIntro from './GameIntro';
const Game = () => {
const [item, setItem] = React.useState();
React.useEffect(() => {
let id;
function next(i) {
id = setTimeout(function() {
if (i < gdatas.length) {
setState(gdatas[i]);
next(i+1);
}
}, 2000);
}
next(0);
return () => clearTimeout(id);
}, []); // only invoke on first render
return (
<div>
{item && <GameIntro gdata={item} />}
</div>
)
}
export default Game;
You don't render the child each item on each loop, just update the props on it. It's actually pretty trivial once you see how:
Example below:
import React, {useState, useEffect, useRef} from "react";
const GameObject = (props) => (
<div className="bar">
{props.current.name}
</div>
)
function App() {
const data = [{name: 'Luke'}, {name: 'Darth'}, {name: 'Yoda'}];
let index = useRef(0);
const [current, setCurrent] = useState(data[index.current]);
useEffect(() => {
function loop() {
setInterval(() => {
index.current = (index.current === data.length - 1) ? 0 : index.current + 1;
setCurrent(data[index.current]);
}, 1000);
}
loop();
}, []);
return (
<div className="App">
<GameObject current={current}/>
</div>
);
}