Skip to content

Instantly share code, notes, and snippets.

@mindplay-dk
Last active January 27, 2024 13:51
Show Gist options
  • Save mindplay-dk/1cd7f487b6ed7a5ab98483cf061b3822 to your computer and use it in GitHub Desktop.
Save mindplay-dk/1cd7f487b6ed7a5ab98483cf061b3822 to your computer and use it in GitHub Desktop.
reactive JS πŸ€” everything is a signal? πŸ€·β€β™‚οΈ
/*
I know this is probably bonkers and there must be a million reasons this wouldn't
actually work, but hear me out... what if variables were reactive by default?? 😏
*/
function fetchTodayFortune() {
return fetch("https://api.example.com/fortune")
.then((response) => response.json())
.then((data) => data.message)
.catch((error) => {
throw error;
});
}
function untilResolved(promise, fallback) {
// Create a reactive variable to hold the result/fallback/error message:
let result = fallback;
// Start the promise and update the result when it resolves.
promise.then((value) => {
result = value;
}).catch(() => {
result = "sorry, no fortune available today..."
});
return result;
}
// Fetch today's fortune and store it in a variable with an initial "loading" message.
const fortune = untilResolved(fetchTodayFortune(), "loading...");
function renderForm() {
// Declare local reactive variables
let firstName = "";
let lastName = "";
let fullName = firstName + " " + lastName;
// Counter for tracking how long the form has been open.
let counter = 0;
// Effect for updating the counter every second.
const intervalId = setInterval(() => {
counter += 1;
}, 1000);
// Render the form and components.
return (
<div>
<input
type="text"
placeholder="First Name"
value={firstName}
onInput={(event) => {
firstName = event.target.value;
}}
/>
<input
type="text"
placeholder="Last Name"
value={lastName}
onInput={(event) => {
lastName = event.target.value;
}}
/>
<p>Welcome, {fullName}!</p>
<p>Form open for: {counter} seconds</p>
<p>Today's Fortune: {fortune}</p>
<button disabled={!firstName || !lastName}>Continue</button>
</div>
) finally {
// Cleanup function to clear the interval when the component is unmounted.
clearInterval(intervalId);
// (finally blocks can be attached to any value and run when garbage-collected,
// in this case when the element is removed from the DOM.)
};
}
// Mount two instances of the form to the DOM.
const form1 = renderForm();
const form2 = renderForm();
const appElement = document.getElementById("app");
appElement.appendChild(form1);
appElement.appendChild(form2);
// Example: Remove one of the forms, and the cleanup function is called.
setTimeout(() => {
appElement.removeChild(form2);
// The cleanup function for form2 will automatically clear its interval timer.
}, 5000); // Remove form2 after 5 seconds as an example.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment