3
optimista
176d

On https://reactjs.org/docs/... it is declared that useEffect runs after render is done.

However... if you put into useEffect an expensive calculation or operation e.g. "add +1 to x billion times", it will get stuck after updating the data, but before the re-render is done.

This leads to inconsistency between the DOM and the state which I believe is a foundational point of react. Moreover, the statement that "useEffect runs after render" is false.

See also: https://stackoverflow.com/questions...

The solution is to add a timeout to that expensive operation, e.g. 50 ms so the re-render can finish itself.

The integrity of my belief in react has received a shrapnel today. Argh :D Guys, how this can be? It seems that useEffect is not being run after re-render.

Comments
  • 1
    Wrong tag.
  • 0
    I am fairly new to react, but I read somewhere useEffect is async. If that’s right, the function is called asynchronously and hence doesn’t block Ui render in normal cases. Whereas in your case, even though it’s async, the continuous calculation/processing is blocking the rendering
  • 0
    But yes, you’re right. It should say that if it doesn’t do that
  • 0
    @mac-aga I think you're mixing asynchronity with multithreading.
  • 0
    Generally if you're doing something computationally expensive, the answer is multithreading, which in websites means web workers. Async is preferable if you have to respond to many events but do very little work each time.
  • 1
    Pretty sure doing a heavy calculation on the UI looper thread is the problem here.
    Just. Don't. Do. Calcs. On The UI Thread.

    There. Crisis of angular faith averted.
  • 1
    https://reactjs.org/docs/...

    As @MagicMirror said, never do expensive calculation front end side.

    Or at least use memoized stuff.
  • 1
    @magicMirror Thank you. That is what I needed to hear.
  • 0
    @100110111 Which one? #devrant? Where else should I have put it?
  • 1
    @optimista rant, obviously. Devrant is reserved for posts concerning the platform itself.
  • 1
    @optimista Sarcasm? Hmmm.
    I approve!

    In any case - when a framework promises that something will "run after something else" it means that it will from a certain object lifecycle perspective. But UI loopers maintain many objects, and many lifecycles that can interfere with each other.....
  • 2
    @100110111 Got ya, apologies. Next time will have in mind!

    @magicMirror haha, actually, it was completely honest, I meant it, truly. I knew I was doing something bad I was just desperately looking to know what it was. useMemo looks like the right way, even though... I doubt it will utilize the memorization as the values are objects and their variation is too big. The chance it will calculate for the same values again is just miniature.

    I will try to find a way to implement it into a my 'useEffect chain' that is responsible for the process of autosaving with all its steps (e.g. generating thumbnail)... As far as I understand, it still can happen that useEffect for autosave can ask for the memoized value before it has been calculated (will receive previous one), but I guess the chance of that is very small and it's a small trade-off for more coherent implementation.
  • 2
    @optimista Ok.
    1. I am not a JS coder. I try to avoid that abomination like Covid-19. Not very successfully though. NodeJS gives me a headache.
    2. I have no idea how angular works specifically. Or Vue. Or any of the other JS frontend frameworks out there.
    3. I am not a frontend dev. When I was.... lets just say some of my work was presented in the "never do this crap" section of an official google page on android UI documentation.

    My knowledge comes from my Android dev experience. But a UI event loop works in a simlar way anywhere. I would suggest you store the heavy calculation results in some kind of an in-memory store, that you update/read from in your lifecycle functions in am easy, and non locking way. The framework you are using should have that functionality builtin - should be used in the async communication layer for example.
Add Comment