3 ms·
I've been building some projects with Crank.js and Mithril, both of which require an explicit function call to rerender the application after changing state. I
by spiffytech 6y ago
I've been building some projects with Crank.js and Mithril, both of which require an explicit function call to rerender the application after changing state.
In theory, that sounds terrible; I don't want to keep track of when my app needs to rerender, or worry about a stale DOM because I forgot to rerender after some event.
In practice, it's a breath of fresh air compared to my work with React/Vue/Svelte. Everything is just so simple; I can use vanilla JS data structures and code organization patterns. I can architect my frontend state and logic in the way that makes the most sense for my domain, instead of ceding control flow to a heavy, footgun-y, limited-expressivity framework that demands to know everything my app does so it can decide on its own when to rerender.
I'm tired of debugging confusing bugs because React hooks mix asynchronous control flow inside the render loop and my app has to have correct rendering and logic for every intermediate state of a chained sequence of useCallback/setState hooks. Tired of telling my team we have to put off a feature because it'll take a week to do something that feels like a 3-hour task because refactoring around a framework's control structures is harder than refactoring ordinary JS features. Tired of magic reactive compilers that create buggy renders and template languages that are only nice to work with if you use the One True Blessed VS Code Plugin, and tired of frameworks that need CLI scaffolding tools because they're more complicated than anyone wants to initialize with a blank editor.
Crank.js, Mithril, and (at a preliminary glance) Forgo are very compelling to me. They offer the declarative, self-contained nature of components that I love from React/Vue/Svelte and the type safety of TypeScript for view code instead of template strings. My whole project scaffolding is just installing esbuild and generating a tsconfig.json. Maybe toss in browser-sync and watchexec if I'm feeling fancy. I don't need to make major architectural decisions based on the preferred state management tool, because these frameworks couldn't care less about how state is managed. And if I really want automatic rerenders, it's 10 LOC to write a reusable ES6 Proxy that returns an object I can dump state values into that will auto refresh if I reassign a property.
And these frameworks still feel like a state machine in the same way React does - view code is declaratively rendered from application state. There is synchronization of state to DOM, but only in the sense that you have to explicitly invoke the declarative engine, and not in the sense that you have to manually synchronize like you would using jQuery to find and change DOM nodes.
Keeping up with manual refreshes feels so simple and easy compared to all the hoops I've jumped though with the household name frameworks.
- daveidol 6y agoThanks for sharing your perspective. I happen to disagree with you on a lot of these things - but I guess I shouldn't be so dismissive about manually rerendering and assuming it won't scale to larger applications. Speaking to your specific examples: I do agree that some of the new React hooks (especially useEffect) seem to promote an ... idealistic idea of how your component should trigger and react to side effects (especially if you enable the eslint plugins) - namely always due to changes in reference equality. If you need to deal with other things (like an ID changing in a nested object that gets recreated on each render) it can be a big headache and error-prone. On the other hand - most of these hooks (and libraries and build tools you are alluding to) are easy to modify or use something else if you don't like them. Personally I find that much easier than building web apps like I used to pre-React and dealing with manual state synchronization. But to each their own! I've seen some pretty clean non-React codebases and I've seen some pretty messy React ones, just as I have on the flip side.
- no_wizard 6y agoSincere question, how many people work on this application or suite of applications? One, ten, twenty? It's as the number of developers grow on projects that these things become nightmares. Having worked somewhere that used React and had extremely strict eslint and typescript settings, it was all so uniform (those type checking static linting really keep the guard rails on code quality) because you were guided to use the same effective patterns in solving those problems. In fact, all the interesting work started happening outside interactions with the framework (and more around redux, in this case) so we were more focused on business logic and other concerns, react fell straight into the background. There were only ~25 developers or so. The ecosystem and the framework really lent itself hand in hand. That shouldn't be left out of discussions like this. I can see this model falling flat on its face after about 6 developers working in this system, especially since there is no adjacent tooling that specifically made to keep the guard rails on code quality. I'd love to hear a counter example to that. Edit: my point is, in order for something to be an acceptable alternative to React, it needs to have the ability to thrive in an example like I gave. React isn't for the 1 man shop, per se, or even perhaps a team of 5-6 developers that can coordinate well. Its real strength is in large application development, with `n` number of developers, where n is greater than 6. Thats just been my experience.