Performance

Whenever the timeframe changes, a recalculation of all the item's width and position must be performed.

When performing operations that require a high amount of sequential changes, like zooming in or panning, the resulted re-renders might cause stuttering and frame-drops.

This "frequent change" problem is quite common in reactive frontend applications, and there are multiple solutions to it.

As you are in full control of the timeframe state, you can apply a chosen mechanism of debouncing to the timeframe state.

This will reduce the amount changes registered in the timeline, and in return reduce the amount of renders required when zooming an panning, resulting in a great improvement in performance.

Here are some common solutions:

If you use React 18+, you should make use of the useDeferredValue API.

useDeferredValue is a React Hook that lets you defer updating a part of the UI.

Code Example

function App() {
  const [timeframe, setTimeframe] = useState(DEFAULT_TIMEFRAME);
  const debouncedTimeframe = useDeferredValue(timeframe);
  
  ...
  
  return (
    <TimelineContext
        onDragEnd={onDragEnd}
        onResizeEnd={onResizeEnd}
        timeframe={debouncedTimeframe} // provide the debounced timeframe
        onTimeframeChanged={setTimeframe}
    >
      <Timeline items={items} rows={rows} />
    </TimelineContext>
  )

🧠 You can still make use of the un-debounced state to render selected components in real-time. For example, you can render the time-axis using the un-debounced state, and render the timeline using the debounced state.

Play around with the live demo, and watch how the timeaxis and the timeframe move asynchronously🔥

Live Example

In this example, You can play around with difference modes and feel the difference between them.

Click here to see the full code

Last updated