score:8
the reason why you did not get updated state is because you called it inside useeffect(() => {}, []) which is only called just once.
useeffect(() => {}, []) works just like componentdidmount().
when gamestart function is called, gameplaytime is 100, and inside gamestart, it uses the same value however the timer works and the actual gameplaytime is changed. in this case, you should monitor the change of gameplaytime using useeffect.
...
useeffect(() => {
if (gameplaytime % targetshowtime === 0) {
const random = (math.floor(math.random() * 10000) % wp("70")) + wp("10");
const targetposition = { x: random, y: hp("90") };
const spininfodata = getspinarray()[math.floor(math.random() * 10) % 4];
newspinshow(targetposition, spininfodata, spinspeed);
}
}, [gameplaytime]);
const gamestart = () => {
gamestartinternal = setinterval(() => {
setgameplaytime(t => t-1);
}, 1000);
};
...
score:4
you shouldn't use setinterval with hooks. take a look at what dan abramov, one of the maintainers of react.js, said regarding an alternative on his blog: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
score:5
https://overreacted.io/making-setinterval-declarative-with-react-hooks/
dan abramov article explain well how to works with hooks, state, and the setinterval() type of api!
dan abramov! is one of the react maintaning team! so known and i pesonally love him!
quick explanation
the problem is the problem of how to access state with a useeffect() that execute only once (first render)!
the short answer is: by the use of refs (useref)! and another useeffect() that run again when update is necessary! or at each render!
let me explain! and check the dan abramov solution! and you'll get better the statement above at the end! with a second example that is not about setinterval()!
=>
useeffect() either run once only, or run in each render! or when the dependency update (when provided)!
accessing state can be possible only through a useeffect() that run and render each relevant time!
or through setstate((state/*here the state*/) => <newstateexpression>)
but if you want to access the state inside useeffect() => rerun is necessary! meaning passing and executing the new callback!
that doesn't work well with setinterval! if you set it each time! the counter get reset! leading to no execution if the component is re-rendering fast!
if you render only once! the state is not updated! as the first run, run a one callback! and make a closure! the state is fixed! useeffect(() => { <run once, state will stay the same> setinterval(() => { <state fixed> }) }, [])
.
for all such kind of situation! we need to use useref! (refs)!
save to it a callback that hold the state! from a useeffect() that rerender each time! or by saving the state value itself in the ref! depending on the usage!
dan abramov solution for setinterval (simple and clean)
that's what you are looking for!
useinteval hook (by dan abramov)
import react, { usestate, useeffect, useref } from 'react';
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]);
}
usage
import react, { usestate, useeffect, useref } from 'react';
function counter() {
let [count, setcount] = usestate(0);
useinterval(() => {
// your custom logic here
setcount(count + 1);
}, 1000);
return <h1>{count}</h1>;
}
we can see how he kept saving the new callback at each re-render! a callback that contain the new state!
to use ! it's a clean simple hook! that's a beauty!
make sure to read dan article! as he explained and tackled a lot of things!
setstate()
dan abramov mentioned this in his article!
if we need to set the state! within a setinteral! one can use simply setstate() with the callback version!
usestate(() => {
setinterval(() => {
setstate((state/*we have the latest state*/) => {
// read and use state
return <newstateexpression>;
})
}, 1000);
}, []) // run only once
we can even use that! even when we are not setting state! possible! not good though! we just return the same state value!
setstate((state) => {
// run right away!
// access latest state
return state; // same value (state didn't change)
});
however this will make different react internal code part to run (1,2,3), and checks! which end by bailing out from re-rendering! just fun to know!
we use this only for when we are updating the state! if not ! then we need to use refs!
another example: usestate() with getter version
to show case the how to work with refs and state access! let's go for another example! here another pattern! passing state in callbacks!
import react from 'react';
function usestate(defaultval) {
// getting the state
const [state, setstate] = react.usestate(defaultvalue);
// state holding ref
const stateref = react.useref();
stateref.current = state; // setting directly here!
// because we need to return things at the end of the hook execution
// not an effect
// getter
function getstate() {
// returning the ref (not the state directly)
// so getter can be used any where!
return stateref.current;
}
return [state, setstate, getstate];
}
the example is of the same category! but here no effect!
however we can use the above hook to access state in the hook simply as bellow!
const [state, usestate, getstate] = usestate(); // our version! not react
// ref is already uptated by this call
react.useeffect(() => {
setinteval(() => {
const state = getstate();
// do what you want with the state!
// it works because of the ref! get state return a value to the same ref!
// which is already updated
}, 1000)
}, []); // running only once
for setinterval()! the good solution is dan abramov hook! making a strong custom hook for a thing is the cool thing to do! this second example is more to showcase the usage and importance of refs, in such state access need or problem!
it's simple! we can always make a custom hook! use refs! and update the state in ref! or a callback that hold the new state! depending on usage! we set the ref on the render (directly in the custom hook [the block execute in render()])! or in a useeffect()! that re-run at each render or depending on the dependencies!
note about useeffect() and refs setting
to note about useeffect()
useeffect => useeffect runs asynchronously and after a render is painted to the screen.
- you cause a render somehow (change state, or the parent re-renders)
- react renders your component (calls it)
- the screen is visually updated
- then useeffect runs
very important of a thing! useeffect() run after render() finish and the screen is visually updated! it run last! you should be aware!
generally however! effects should be run on useeffect()! and so any custom hook will be ok! as it's useeffect() will run after painting and before any other in render useeffect()! if not! as like needing to run something in the render directly! then you should just pass the state directly! some people may pass a callback! imagine some logic component! and a getstate callback passed to it! not a good practice!
and if you do something somewhere of some of such sense! and talking about ref! make sure the refs are updated right! and before!
but generally you'll never have a problem! if you do then it's a smell! the way you are trying to go with is high probably not the right good way!
in the whole i hope that gave you a good sense!
score:7
you're creating a closure because gamestart()
"captures" the value of gameplaytime
once when the useeffect hook runs and never updates after that.
to get around this, you must use the functional update pattern of react hook state updating. instead of passing a new value directly to setgameplaytime()
, you pass it a function and that function receives the old state value when it executes and returns a new value to update with. e.g.:
setgameplaytime((oldvalue) => {
const somenewvalue = oldvalue + 1;
return somenewvalue;
});
try this (essentially just wrapping the contents of your setinterval function with a functional state update):
const [gameplaytime, setgameplaytime] = react.usestate(100);
let targetshowtime = 3;
// call function
react.useeffect(() => {
gamestart();
}, []);
const gamestart = () => {
gamestartinternal = setinterval(() => {
setgameplaytime((oldgameplaytime) => {
console.log(oldgameplaytime); // will print previous gameplaytime value
if (oldgameplaytime % targetshowtime === 0) {
const random = (math.floor(math.random() * 10000) % wp("70")) + wp("10");
const targetposition = { x: random, y: hp("90") };
const spininfodata = getspinarray()[math.floor(math.random() * 10) % 4];
newspinshow(targetposition, spininfodata, spinspeed);
}
return oldgameplaytime - 1;
});
}, 1000);
};
Source: stackoverflow.com
Related Query
- Can not update state inside setInterval in react hook
- State not updating when using React state hook within setInterval
- How to properly update an array inside a react hook state
- React useState() hook does not update state when child.shouldComponentUpdate() returns false
- setState does not update state immediately inside setInterval
- React testing library: An update inside a test was not wrapped in act(...) & Can't perform a React state update on an unmounted component
- React update state hook on functional component does not allow dot notation
- React does not re-render all componenets on state update in a custom hook
- React cannot set state inside useEffect does not update state in the current cycle but updates state in the next cycle. What could be causing this?
- useState React Hook set method does not update state immediately in onChange()
- Can not get latest state in React hook | Stale Closure Issue
- React hook state - does not update component
- React Hooks: Instantiating state hooks on validation Error: Invalid hook call. Hooks can only be called inside of the body of a function component
- React state update error whenever i open someone's image, and image not redering too. How can I fix this error
- React state not updating inside setInterval
- React State is not getting update before assertion even acting inside act function
- Why useState in React Hook not update state
- How can I re-trigger a custom hook inside my react component, when its states have not changed?
- how can i add setinterval function inside React new array state
- State does not update React Hook
- Can I set state inside a useEffect hook
- UI not re-rendering on state update using React Hooks and form submission
- how to update multiple state at once using react hook react.js
- Can not pass state with react router dom v6 beta, state is null
- React does not refresh after an update on the state (an array of objects)
- React not re-rendering after array state update
- React update state if image not found.
- React Hook useCallback not updating State value
- React js changing state does not update component
- Access old state to compare with new state inside useEffect react hook with custom hooks usePrevious
More Query from same tag
- When I try to push an element to a array but it takes only one rest of the elements are got removed automatically. It happen when use useState hook
- Why do these uncontrolled radio inputs require two clicks to be selected?
- Creating a new room (including inputs and button) and only template shows without the values inside (rcc)
- Call function on button press - react
- Triangle Button Slider In ReactJS/MaterialUI
- React component responsible for receiving data from a product and rendering it is rendered before the data arrives
- How to pass a state from component to a parent - the App.js (click outside to close navbar)
- Is there a way to limit filtering combo box onChange API calls?
- jest test call of method that is not mocked
- Running react-scripts app with input from another server
- Toggle dropdown menu in reactjs
- Add styles to only sticky elements with react-table-sticky
- Is it possible to query firebase-firestore data by multiple criteria/values
- React useEffect hook causes DOMException: User activation is required to request permissions
- How to update my react state with active tab menu name so it can pass on to the endpoint call?
- React.js infinite re-render
- React js, how to update state object values on input change?
- How to retrieve data from firebase v9 to display it on the frontend?
- How to make translation runtime
- React - Cannot read property 'setState' of null
- ReactJS - Added non-passive event listener to a scroll-blocking 'mousewheel' event
- React complains element type is invalid when trying to use context
- React Typescript types for monaco-editor
- Import scss in react
- TextField Style using styed-components and Material-UI withStyles
- Is this an issue with the server code, or the app code?
- Pick a type from one of the props
- Image in NextJS does not allow template literals inside src when deploying on vercel
- Undertake operations upstream to Docusaurus and ensure the correct order of loading files
- Socket.io Server Emit only works after server restart