Ensuring React state has updated for game loop
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 |
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 '18 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 '18 at 14:15
add a comment |
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 '18 at 14:03
wbruntrawbruntra
425414
425414
1
setState
can take a callback function which executes after the new state has completely propagated.
– MTCoster
Nov 19 '18 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 '18 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 '18 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 '18 at 14:15
1
1
setState
can take a callback function which executes after the new state has completely propagated.– MTCoster
Nov 19 '18 at 14:06
setState
can take a callback function which executes after the new state has completely propagated.– MTCoster
Nov 19 '18 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 '18 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 '18 at 14:15
add a comment |
3 Answers
3
active
oldest
votes
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 |
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
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
Nov 24 '18 at 14:54
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 |
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 |
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 '18 at 14:52
streletssstreletss
2,388521
2,388521
add a comment |
add a comment |
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
SetState is Asynchronous
this.setState({
running: true,
});
To make it synchronously execute a method:
this.setState({
value: true
}, function() {
this.functionCall()
})
add a comment |
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 '18 at 14:36
J DorrianJ Dorrian
1156
1156
add a comment |
add a comment |
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
Nov 24 '18 at 14:54
add a comment |
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
Nov 24 '18 at 14:54
add a comment |
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 '18 at 14:42
Pranay TripathiPranay Tripathi
517411
517411
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
Nov 24 '18 at 14:54
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
Nov 24 '18 at 14:54
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
Nov 24 '18 at 14:54
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
Nov 24 '18 at 14:54
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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 '18 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 '18 at 14:15