I've created a simple draggable component. I'm using the react-swipeable
library but my question is about any event which repeatedly and in quick succession updates useState
.
With the console.log
in onSwiping
I can see that the function is called many times per second, which is what I need to update the position of the component. This works however is there a performance issue with calling setSwipeX
so frequently?
The entire component will re-render very fast as it's dragged. Is this OK or would it be better to just update swipeX
without re-rendering the entire component, and is this even possible?
import React from "react";
import { useSwipeable } from "react-swipeable";
export default function App() {
const [swipeX, setSwipeX] = React.useState(0);
const swipeHandlers = useSwipeable({
onSwiping: (e) => {
console.log(e);
setSwipeX(-e.deltaX);
},
trackMouse: true
});
return (
<div
className="App"
{...swipeHandlers}
style={{
transform: `translateX(${swipeX}px)`
}}
>
<h1>Stuff</h1>
</div>
);
}
https://codesandbox.io/s/relaxed-minsky-ni7n9?file=/src/App.js
To optimize React rendering, you need to make sure that components receive only necessary props. It will let you control the CPU consumption and avoid over-rendering unnecessary features. The solution is to create a functional component that will collect all props and redistribute them to other components.
1. Memoization using useMemo() and UseCallback() Hooks. Memoization enables your code to re-render components only if there's a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications.
To solve this react itself has a native solution, which is code-splitting and lazy loading. Which allows splitting bundle files into a smaller size. The best place to introduce code splitting is in routes. Route-based code splitting solve half of the issues.
I'm not an expert when it comes to performance, but I have implemented a couple of weeks ago a component that lets you swipe down page component. It was very similar to what you were doing, but vertically. First time I tried to do so with useState, I had no issues on my Pixel 3a. But when I tested it on Nexus 5x, it wasn't smooth at all. When I changed the logic to work with useRef instead of userState, it felt much smoother. Something like this:
import React from "react";
import { useSwipeable } from "react-swipeable";
export default function App() {
const ref = React.useRef(null);
const swipeHandlers = useSwipeable({
onSwiping: (e) => {
console.log(e);
ref.style.transform = `translateX(${-e.deltaX}px)`;
},
trackMouse: true
});
return (
<div
className="App"
{...swipeHandlers}
ref={ref}
>
<h1>Stuff</h1>
</div>
);
}
This way, you change the DOM directly. As mentioned again, I didn't test it by numbers, but physically on a low end device I could see a bit of difference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With