4 ms·
Nice demo of sluggishness of React: https://react.dev/learn/updating-objects-in-state https://react.dev/learn/updating-objects-in-state https://megous.com/dl/
by megous 4y ago
Nice demo of sluggishness of React:
https://react.dev/learn/updating-objects-in-state https://react.dev/learn/updating-objects-in-state
https://megous.com/dl/tmp/zyrzbzjqxccvvdniorpj.webm https://megous.com/dl/tmp/zyrzbzjqxccvvdniorpj.webm
(Top of the line desktop AMD chip.)
The code has no transition, no setTimeout, no nothing that would indicate any delay. The dot should always be right under the cursor. This will happen with every similar UI pattern (want to resize something, move a slider, etc. etc.)
I guess this is a result of tradeoffs React has to do by insulating people from DOM.
There's probably some way to force immediate DOM update, but then you're pulling in a lot of useless diffing and checking for each frame, instead of just updating the single el.style.something property you'd do when directly using DOM API and leaving the browser to do the rest.
- senttoschool 4y ago>(Top of the line desktop AMD chip.) Slightly off topic but my M1 Pro Apple Silicon Mac does not lag like your top of the line AMD chip. I know most consumers run React code with CPUs slower than Apple Silicon chips but this post is more of an endorsement for the M1 lineup.
- megous 4y agoYou're comparing different software rather than different CPUs.
- geodel 4y agoThis is relief. I was afraid that M1 Max would be minimum requirement for smooth experience.
- senttoschool 4y agoI know your post is sarcasm but a base M1 would perform the same as M1 Pro, Max, Ultra in this case. It's the single thread speed that matters the most in web performance. So you just need an M1. The M1 Air is frequently on sale for $800 nowadays. Or if you're really on a budget, you can buy a used M1 Mini on eBay for $400. Very affordable for those who want high browser performance.
- jhugo 4y agoZero lag on my M1 MacBook Air too.
- andrewmcwatters 4y agoThis doesn't have anything to do with React, it has to do with refresh rate, vertical sync, and the fact that your cursor position is updated by hardware and doesn't undergo the same update process as the rest of UI compositing in an operating system. Draw a software cursor, and the same exact thing happens. In fact, in effect, the red dot is a software cursor. You can accomplish visualizing the same lag in a traditional update-draw loop in game software. Cursors are special. Sibling comments here don't experience the same effect, because they're running displays at higher refresh rates. That's it.
- megous 4y agoHm, right. Good to be corrected. Not sure why the lag is so big, though. Looks like it's 3 frames looking at slowmo capture of the screen. I guess you can take your cursor position at the beginning of scanout of the previous frame, render the new browser layer content, tell the compositor to update both cursor layer position, and browser layer at the next scanout, and both should have matching positions on the next frame. Maybe if the compositor is updating the cursor layer position from mouse position known right at the momen of atomic commit, there may be some difference. Well, this is Xorg I'm using, and it's not using atomic DRM API, so things are not well synchronized.
- ajkjk 4y agoFor anything like animation in React I would use CSS transitions or using direct updates on refs without triggering rerenders. It takes only a simple model of "what a rerender is" to understand that this is running potentially _way_ more code than it needs to for every update and injecting scripting frames before the actual animation update happens. So this should be `ref.current.style = {x: <whatever>, y: whatever}`. It's also a great use for useImperativeHandle() if it gets any more complicated. This is the example from the docs updated to use a ref: https://codesandbox.io/s/lucid-grothendieck-iquzfj?file=/App.js https://codesandbox.io/s/lucid-grothendieck-iquzfj?file=/App... On this example it pretty much looks the same, which I assume is because of what the sibling comment says, that any cursor drawn in software is going to be slower than in hardware, and the animation and app are trivial so the rerender is basically free. But this way is still better, and it'll be more obviously better if the components being animated are complex. There's not going to be any way to do it faster in JS, but React can be a lot slower depending on what happens on rerenders (which is often, if using imported components, somewhat out of your control).
- herpderperator 4y agoApple M1: https://www.dropbox.com/s/ivz9hr2pcer5pt1/react_dot.mov?dl=0 https://www.dropbox.com/s/ivz9hr2pcer5pt1/react_dot.mov?dl=0
- dmak 4y agoIf you're doing anything animation related, there is no point in using React's useState because it causes re-renders. The right approach here is to use useRef.
- mmis1000 4y agoDo you have mouse that have much higher update rate than monitor? The mouse event frequency is generally capped at the update rate of monitor unless you use `pointerrawupdate` which will actually give you raw mouse event without delay.
- Rapzid 4y agoThere will always be the potential for lag because the OS UI thread is updating the native mouse pointer position separately from the browser UI thread updating the page. A similar issue occurs with native scrolling and fixed position elements whose positions need update every frame. You must take control of the scrolling in JS in order to prevent jitter.
- mattgperry 4y agoYour intuition is correct - there's nothing to indicate any delay. Look at your profiler. Notice any significant overhead? You don't. Implement this same thing using events and `.style` directly. You will get the exact same result. The pointerEvent => style feedback loop is unfortunately very slow, more or less so in different browsers/operating systems. Interesting that you would know so little about this and yet feel confident enough to make a proclamation like this is evidence of React's performance.