question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Async access to current state, outside actions

See original GitHub issue

Abstract / TL;DR; When you try to access the state asynchronously in the view, like in onbeforeremove or in setTimeout called in event handlers, the state will be stale. There are workarounds, but they are not ideal.

The long version:

If you define a function inside the view, which will be called at a later time, that function will not have access to the current state at the time it is called. If you try, the state you get will be stale. This means, for example, you cannot rely on state inside onbeforeremove handlers, or in setTimeouts called in event handlers. For a concrete demonstration of this problem, see this example of a carousel:

https://codepen.io/zaceno/pen/WdrZdK

I’m using hyperapp-transitions in order to have a not too contrived, but still short, example. All you need to know is that

  1. transitions.exit runs the transition in the onbeforeremove handler.
  2. The function passed to the css prop is called at the time of the transition, in this case to determine the direction to exit/enter. (Since it depends on where the user clicked)

Notice when you click the buttons of the carousel that as long as you times in a row, the new images slide in the same direction as the old images slide out. But every time you switch directions, the image leaves according to the old direction, while the new image slides in from the correct direction.

The explanation for this, is that the exit transition (and hence onbeforeremove handler, has the old state in it’s closure) – it hasn’t ever even seen the new state, since it’s no longer in the vtree (that’s why its being removed).

There are, of course, workarounds…

One way to solve it, would be to keep an up to date copy of the relevant state somewhere, accessible by the functions that need it. That’s how I solved it for the caruousel example in this codepen:

https://codepen.io/zaceno/pen/LeGQab?editors=0010

See especially lines 14, 32, 37, 38. Notice how now when you switch directions, it works as intended. This works for the occasional one off, but is obviously far from ideal.

Another solution is to use an action (since actions are special, and always have access to the current state when they’re called), relying on the fact that actions return their partial state. See:

https://codepen.io/zaceno/pen/ZvQrgE?editors=0010 (notice lines 14, 16, 22)

This solution is better than the previous, but also unsatisfying (for me at least). It’s annoying that simply accessing the state will cause an update and rerender.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
jorgebucarancommented, Dec 19, 2017

@zaceno getState does not cause a re-render.

const actions = {
  getState: () => state => state
}
0reactions
jorgebucarancommented, Jan 3, 2018

👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Redux Fundamentals, Part 6: Async Logic and Data Fetching
It only knows how to synchronously dispatch actions, update the state by calling the root reducer function, and notify the UI that something...
Read more >
Set loading state before and after an action in a React class ...
8. I took it a step further and did const asyncSetState = instance => newState => new Promise(resolve => instance.setState(newState, resolve)); which you...
Read more >
useReducer's dispatch should return a promise ... - GitHub
It's sometimes useful to be able to dispatch an action from within an async function, wait for the action to transform the state, ......
Read more >
Zustand for State Management - This Dot Labs
Zustand can work outside of React with any JavaScript framework, or just with vanilla JavaScript, without any framework, by using 'zustand/ ...
Read more >
Beware: React setState is asynchronous! | by Tomas Carnecky
I recently fixed a bug in one of my applications whose root cause was that I was calling setState multiple times during a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found