A simple utility that limits the impact of functions the demand high CPU load.
Functionality that demands intense CPU load can create a poor user experience as their session can hang and become unresponsive.
There are throttle and debounce solutions that help to alleviate the repercussions of CPU intensive UI. Eggs Benedict incorporates these methodologies into a lightweight React and Vanilla JS abstraction.
Eggs Benedict was originally designed to help with the various complex calculations associated with the Avocado application. The library has since been enhanced into a simple developer API that can yield powerful results.
This library uses Request Animation Frame to implement throttle and debounce solutions simultaneously. This provides the real-time updates of a throttler while ensuring that the UI does not fall out of sync with a debouncer.
Eggs Benedict offers some light configuration for custom throttle and debounce delays.
{
throttleDelay: 0, // Default.
debounceDelay: 100 // Default.
}
Take a look at the interactive CodeSandbox to see configuration examples and their correlation with different CPU loads.
You can reference the Eggs Benedict types directly in your application.
import { Options } from "eggs-benedict/types";
You can also supply a typed callback as a generic to the React Hooks and Vanilla JS initializers.
// prettier-ignore
const setLoadControlValue =
useLoadControl<(value: string) => void>(callback);
// prettier-ignore
const [activeLoadControl, cleanUpLoadControl] =
LoadControl<(value: string) => void>(callback);
In this example we are using the React Hooks import to run some CPU heavy work when the Range <input />
changes its value.
import React from "react";
import { useLoadControl } from "eggs-benedict/hooks";
export default function App() {
const [count, setCount] = React.useState(0);
const heavyCpuLoad = (value) => {
/**
* CPU HEAVY WORK HERE!
* - - - - - - - - - - -
* Maybe some complex calculations based on the Range <input /> value 🤓
*/
setCount(value);
};
const setLoadControlCount = useLoadControl(heavyCpuLoad);
const handleChange = (event) =>
setLoadControlCount(event.currentTarget.value);
return (
<>
<input type="range" value={count} onChange={handleChange} />
<p>{count}</p>
</>
);
}
In this example we are using a Vanilla JS implementation inside a React useEffect
scaffold. When the user scrolls the window
we run a CPU heavy callback.
import React from "react";
import LoadControl from "eggs-benedict";
export default function App() {
const [scroll, setScroll] = React.useState(0);
React.useEffect(() => {
const heavyCpuLoad = (event) => {
/**
* CPU HEAVY WORK HERE!
* - - - - - - - - - - -
* Maybe slow DOM heavy math to move some elements around 🤓
*/
setScroll(event.currentTarget.scrollY);
};
const [scrollLoadControl, cleanUpScrollLoadControl] = LoadControl(
heavyCpuLoad
);
window.addEventListener("scroll", scrollLoadControl);
/**
* Remember to remove the Eggs Benedict instance when unmounting your
* <Component /> 👍
*/
return cleanUpScrollLoadControl;
}, []);
return (
<>
<p style={{ position: "fixed" }}>{scroll}</p>
<div
style={{
height: "200vh",
backgroundImage: "linear-gradient(to bottom, #58FFC7, #2D8165)",
}}
/>
</>
);
}