Ensuring React state has updated for game loop
up vote
4
down vote
favorite
I am writing a version of Conway's Game of Life in React. The component's state contains the grid
describing which of the cells is alive at the current time. In each game loop, the new grid
is calculated and the state is updated with the next iteration.
It occurs to me that since setState
is asynchronous, when repeatedly calling the iterate
function with setInterval
, I am not guaranteed to be using the current version of grid
each time iterate
runs.
Is there an alternative to using setInterval
in React that would avoid any potential issues caused by setState
being asynchronous?
Here are the relevant functions that describe the game loop:
go = () => {
const { tickInterval } = this.state;
this.timerId = setInterval(this.iterate, 570 - tickInterval);
this.setState({
running: true,
});
};
iterate = () => {
const { grid, gridSize, ticks } = this.state;
const nextGrid = getNextIteration(grid, gridSize);
this.setState({
grid: nextGrid,
ticks: ticks + 1,
});
};
javascript reactjs
add a comment |
up vote
4
down vote
favorite
I am writing a version of Conway's Game of Life in React. The component's state contains the grid
describing which of the cells is alive at the current time. In each game loop, the new grid
is calculated and the state is updated with the next iteration.
It occurs to me that since setState
is asynchronous, when repeatedly calling the iterate
function with setInterval
, I am not guaranteed to be using the current version of grid
each time iterate
runs.
Is there an alternative to using setInterval
in React that would avoid any potential issues caused by setState
being asynchronous?
Here are the relevant functions that describe the game loop:
go = () => {
const { tickInterval } = this.state;
this.timerId = setInterval(this.iterate, 570 - tickInterval);
this.setState({
running: true,
});
};
iterate = () => {
const { grid, gridSize, ticks } = this.state;
const nextGrid = getNextIteration(grid, gridSize);
this.setState({
grid: nextGrid,
ticks: ticks + 1,
});
};
javascript reactjs
1
setState
can take a callback function which executes after the new state has completely propagated.
– MTCoster
Nov 19 at 14:06
Withthis.timerId
coming fromsetInterval
, I can easily stop the loop by callingclearInterval
. Using callbacks, I guess the callback function would be usingsetTimeout
? What would be the way to stop a loop consisting of callback functions?
– wbruntra
Nov 19 at 14:15
add a comment |
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I am writing a version of Conway's Game of Life in React. The component's state contains the grid
describing which of the cells is alive at the current time. In each game loop, the new grid
is calculated and the state is updated with the next iteration.
It occurs to me that since setState
is asynchronous, when repeatedly calling the iterate
function with setInterval
, I am not guaranteed to be using the current version of grid
each time iterate
runs.
Is there an alternative to using setInterval
in React that would avoid any potential issues caused by setState
being asynchronous?
Here are the relevant functions that describe the game loop:
go = () => {
const { tickInterval } = this.state;
this.timerId = setInterval(this.iterate, 570 - tickInterval);
this.setState({
running: true,
});
};
iterate = () => {
const { grid, gridSize, ticks } = this.state;
const nextGrid = getNextIteration(grid, gridSize);
this.setState({
grid: nextGrid,
ticks: ticks + 1,
});
};
javascript reactjs
I am writing a version of Conway's Game of Life in React. The component's state contains the grid
describing which of the cells is alive at the current time. In each game loop, the new grid
is calculated and the state is updated with the next iteration.
It occurs to me that since setState
is asynchronous, when repeatedly calling the iterate
function with setInterval
, I am not guaranteed to be using the current version of grid
each time iterate
runs.
Is there an alternative to using setInterval
in React that would avoid any potential issues caused by setState
being asynchronous?
Here are the relevant functions that describe the game loop:
go = () => {
const { tickInterval } = this.state;
this.timerId = setInterval(this.iterate, 570 - tickInterval);
this.setState({
running: true,
});
};
iterate = () => {
const { grid, gridSize, ticks } = this.state;
const nextGrid = getNextIteration(grid, gridSize);
this.setState({
grid: nextGrid,
ticks: ticks + 1,
});
};
javascript reactjs
javascript reactjs
asked Nov 19 at 14:03
wbruntra
425414
425414
1
setState
can take a callback function which executes after the new state has completely propagated.
– MTCoster
Nov 19 at 14:06
Withthis.timerId
coming fromsetInterval
, I can easily stop the loop by callingclearInterval
. Using callbacks, I guess the callback function would be usingsetTimeout
? What would be the way to stop a loop consisting of callback functions?
– wbruntra
Nov 19 at 14:15
add a comment |
1
setState
can take a callback function which executes after the new state has completely propagated.
– MTCoster
Nov 19 at 14:06
Withthis.timerId
coming fromsetInterval
, I can easily stop the loop by callingclearInterval
. Using callbacks, I guess the callback function would be usingsetTimeout
? What would be the way to stop a loop consisting of callback functions?
– wbruntra
Nov 19 at 14:15
1
1
setState
can take a callback function which executes after the new state has completely propagated.– MTCoster
Nov 19 at 14:06
setState
can take a callback function which executes after the new state has completely propagated.– MTCoster
Nov 19 at 14:06
With
this.timerId
coming from setInterval
, I can easily stop the loop by calling clearInterval
. Using callbacks, I guess the callback function would be using setTimeout
? What would be the way to stop a loop consisting of callback functions?– wbruntra
Nov 19 at 14:15
With
this.timerId
coming from setInterval
, I can easily stop the loop by calling clearInterval
. Using callbacks, I guess the callback function would be using setTimeout
? What would be the way to stop a loop consisting of callback functions?– wbruntra
Nov 19 at 14:15
add a comment |
3 Answers
3
active
oldest
votes
up vote
0
down vote
accepted
If you need to set state based on a current state, it is wrong to directly rely on this.state
, because it may be updated asynchronously. What you need to do is to pass a function
to setState
instead of an object:
this.setState((state, props) => ({
// updated state
}));
And in your case it would be something like:
iterate = () => {
this.setState(state => {
const { grid, gridSize, ticks } = state;
const nextGrid = getNextIteration(grid, gridSize);
return {
grid: nextGrid,
ticks: ticks + 1
}
});
};
add a comment |
up vote
0
down vote
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
up vote
0
down vote
If you have a look at the react official documentation, the setState
api does take a callback in following format:
setState(updater[, callback])
Here the first argument will be your modified state
object and second argument would be callback function to be executed when setState
has completed execution.
As per the official docs:
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
You can have a look at official docs to get more information on this.
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to theupdater
function will use the most up-to-date version ofstate
, so I think the answer from streletss is easier to implement.
– wbruntra
yesterday
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
If you need to set state based on a current state, it is wrong to directly rely on this.state
, because it may be updated asynchronously. What you need to do is to pass a function
to setState
instead of an object:
this.setState((state, props) => ({
// updated state
}));
And in your case it would be something like:
iterate = () => {
this.setState(state => {
const { grid, gridSize, ticks } = state;
const nextGrid = getNextIteration(grid, gridSize);
return {
grid: nextGrid,
ticks: ticks + 1
}
});
};
add a comment |
up vote
0
down vote
accepted
If you need to set state based on a current state, it is wrong to directly rely on this.state
, because it may be updated asynchronously. What you need to do is to pass a function
to setState
instead of an object:
this.setState((state, props) => ({
// updated state
}));
And in your case it would be something like:
iterate = () => {
this.setState(state => {
const { grid, gridSize, ticks } = state;
const nextGrid = getNextIteration(grid, gridSize);
return {
grid: nextGrid,
ticks: ticks + 1
}
});
};
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
If you need to set state based on a current state, it is wrong to directly rely on this.state
, because it may be updated asynchronously. What you need to do is to pass a function
to setState
instead of an object:
this.setState((state, props) => ({
// updated state
}));
And in your case it would be something like:
iterate = () => {
this.setState(state => {
const { grid, gridSize, ticks } = state;
const nextGrid = getNextIteration(grid, gridSize);
return {
grid: nextGrid,
ticks: ticks + 1
}
});
};
If you need to set state based on a current state, it is wrong to directly rely on this.state
, because it may be updated asynchronously. What you need to do is to pass a function
to setState
instead of an object:
this.setState((state, props) => ({
// updated state
}));
And in your case it would be something like:
iterate = () => {
this.setState(state => {
const { grid, gridSize, ticks } = state;
const nextGrid = getNextIteration(grid, gridSize);
return {
grid: nextGrid,
ticks: ticks + 1
}
});
};
answered Nov 19 at 14:52
streletss
2,025321
2,025321
add a comment |
add a comment |
up vote
0
down vote
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
up vote
0
down vote
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
up vote
0
down vote
up vote
0
down vote
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
answered Nov 19 at 14:36
J Dorrian
1156
1156
add a comment |
add a comment |
up vote
0
down vote
If you have a look at the react official documentation, the setState
api does take a callback in following format:
setState(updater[, callback])
Here the first argument will be your modified state
object and second argument would be callback function to be executed when setState
has completed execution.
As per the official docs:
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
You can have a look at official docs to get more information on this.
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to theupdater
function will use the most up-to-date version ofstate
, so I think the answer from streletss is easier to implement.
– wbruntra
yesterday
add a comment |
up vote
0
down vote
If you have a look at the react official documentation, the setState
api does take a callback in following format:
setState(updater[, callback])
Here the first argument will be your modified state
object and second argument would be callback function to be executed when setState
has completed execution.
As per the official docs:
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
You can have a look at official docs to get more information on this.
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to theupdater
function will use the most up-to-date version ofstate
, so I think the answer from streletss is easier to implement.
– wbruntra
yesterday
add a comment |
up vote
0
down vote
up vote
0
down vote
If you have a look at the react official documentation, the setState
api does take a callback in following format:
setState(updater[, callback])
Here the first argument will be your modified state
object and second argument would be callback function to be executed when setState
has completed execution.
As per the official docs:
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
You can have a look at official docs to get more information on this.
If you have a look at the react official documentation, the setState
api does take a callback in following format:
setState(updater[, callback])
Here the first argument will be your modified state
object and second argument would be callback function to be executed when setState
has completed execution.
As per the official docs:
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
You can have a look at official docs to get more information on this.
answered Nov 19 at 14:42
Pranay Tripathi
31719
31719
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to theupdater
function will use the most up-to-date version ofstate
, so I think the answer from streletss is easier to implement.
– wbruntra
yesterday
add a comment |
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to theupdater
function will use the most up-to-date version ofstate
, so I think the answer from streletss is easier to implement.
– wbruntra
yesterday
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to the
updater
function will use the most up-to-date version of state
, so I think the answer from streletss is easier to implement.– wbruntra
yesterday
If I understood the docs correctly, I don't actually need to use the callback, the first argument supplied to the
updater
function will use the most up-to-date version of state
, so I think the answer from streletss is easier to implement.– wbruntra
yesterday
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53376333%2fensuring-react-state-has-updated-for-game-loop%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
setState
can take a callback function which executes after the new state has completely propagated.– MTCoster
Nov 19 at 14:06
With
this.timerId
coming fromsetInterval
, I can easily stop the loop by callingclearInterval
. Using callbacks, I guess the callback function would be usingsetTimeout
? What would be the way to stop a loop consisting of callback functions?– wbruntra
Nov 19 at 14:15