https://css-tricks.com/reactive-jquery-for-spaghetti-fied-le...
https://css-tricks.com/reactive-jquery-for-spaghetti-fied-le...
I kid you not, there were 30+ redux actions chaining in the most incomprehensible ways, the form literally had a textual input, a button to open the file explorer and a submit button.
It took few weeks one of their Romanian team to build it and apparently that team was reassigned and nobody could touch it without them.
I remember writing pages and pages of notes to understand how this all tied up in those extremely complex chains and claiming progress after few hours when I achieved to simplify the flow by removing a handful of these actions. Hooray.
Then it suddenly dawned on me that...I could just rewrite it from scratch.
Nuked the entirety of that nonsense and replaced it with a single useState in a matter of few hours also implemented the newly requested features.
The client could not believe my progress and the fact I also removed many of their previous issues.
Then I had a second realization: React was useless too and it got dropped for native HTML forms and a handful of JS callbacks.
I 100% believe this, as it describes all the redux codebases I've seen. The library seems to be an antipattern of indirection.
Even now I am not sure I could find a better tool to deal with real time data and synchronization. But for simple crud Redux is mostly overkill
For the anecdote, I remember my manager admitting we can't fix the legacy app, but we can put lipstick on the pig with React.
And in the same way faang is filled with leetcode blackbelt charlatans writing slop, so is Romania apparently.
I'm sure you'd 100% approve of such a statement of your country when based on one anecdotal recount (even if it true).
I was making a point that whether you graduate or not has little correlation with your capacity of handling higher abstractions and complexity, because neither bootcampers nor engineering graduates have the experience of building complex systems, let alone under time, tech leadership and management pressure.
It is likely that the original authors may have found themselves in a situation where they were tasked to build a trivial form with technologies they were not accustomed to at the request of some superior and they ended writing a soup.
Well structured redux (or mobx or zustand for that matter) can be highly maintainable & performant, in comparison to a codebase with poorly thought out useState calls littered everywhere and deep levels of prop drilling.
Redux Toolkit has been a nice batteries-included way to use redux for a while now https://redux-toolkit.js.org/
But the popularity of Redux especially in the earlier days of react means there are quite a lot of redux codebases around, and by now many of them are legacy.
Auto-generated actions from slices are a codified way to do what was once considered an antipattern: Tying an action directly to a single reducer, instead of actions being an action the user could do on a page (which multiple reducers could respond to).
To be fair, jQuery was a response to the the IE and JS variant mess of the early 2000s. jQuery made development possible without debugging across three browser varients.
I just try and get LLMs to do it for me because I'm lazy, and they like to use setInterval instead of mutationObservers and if it works, I just live with the inefficiency.
Oh the horrible things I do with Instagram...
function awaitElement(selector) {
return awaitPredicate(selector, _ => true);
}
function awaitPredicate(selector, predicate) {
return new Promise((resolve, _reject) => {
for (const el of document.querySelectorAll(selector)) {
if (predicate(el)) {
resolve(el);
return;
}
}
// Create a MutationObserver to listen for changes
const observer = new MutationObserver((_mutations, obs) => {
// You could search just inside _mutations instead of the entire DOM.
// Efficiency will depend primarily on how precise your selector is.
for (const el of document.querySelectorAll(selector)) {
if (predicate(el)) {
resolve(el);
obs.disconnect(); // Don't forget to disconnect the observer!
break;
}
}
});
// Start observing the document
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
});
}If someone is still using jQuery for legacy reasons, BackboneJS might be a good intermediate step before going for a modern framework. Backbone is pretty light and pretty easy to grasp
Browser extension options pages are mostly a form mapped to what you have stored in the Storage API, so implementing them by handling the change event on a <form> wrapping all the options (no manual event listener boilerplate) then calling a render() function which applies classes to relevant elements (<body> classes are so good for conditionally showing/hiding things without manually touching the DOM), updates all form fields via named form.elements and re-generates any unique UI elements makes it so un-painful to change things without worrying you're missing a manual DOM update somewhere.
My options pages are Zen Garden-ing 5 different browser-specific UI themes from the same markup to match their host browsers, which is a brittle nightmare to maintain in an app which needs to change over time rather than static demo HTML, but once you've tamed the CSS, the state handling and re-rendering is so painless I'm sticking with it for a while yet, even though it would be long-term easier if I used Preact+htm for no-build option components which know what the active theme is and can generate specific UI for it.
My favourite dirty old-school knowledge is still the named global created for an element with an id, why bother selecting an element when it's right there (once you know you need to avoid global name collisions)?. I use those suckers all the time for quick fun stuff and one-off tool pages.
<h3 id="communityNoteHeading">
Readers added context they thought people might want to know
</h3>
<div>
<textarea id="communityNote" placeholder="Note" rows="5" style="width: 400px"></textarea>
</div>
<button id="communityNoteCopyButton" type="button">Copy</button>
<script>
communityNoteCopyButton.addEventListener('click', () => {
navigator.clipboard.writeText([
communityNoteHeading.innerText,
communityNote.value,
].join('\n\n'))
communityNoteCopyButton.innerText = 'Copied'
setTimeout(() => communityNoteCopyButton.innerText = 'Copy', 1000)
})
</script>