3 ms·
This information is outdated (2020), untrue, and confusing. Both class-based and functional methods achieve the same ends, as they must because all programs mu
by dtagames 2y ago
This information is outdated (2020), untrue, and confusing.
Both class-based and functional methods achieve the same ends, as they must because all programs must have state and side effects. This article starts out saying that we can "simulate" state and side effects with hooks in React, then ends up saying that functional React doesn't have hooks or state! We can't have it both ways.
It is true that functional-style React is "more functional style" than class-based React, but that doesn't alleviate the responsibility of managing class and state. It only puts them in more places and makes us, the programmers, keep track of it across all those places, rather than encapsulating them inside a class.
I adore functional programming and have advocated[0] for it extensively. But I've also used Lit, a class-based reactive web component starter kit, and I must say that the class encapsulation and access to this in Lit makes those components easier to reason about, update, and extend[1].
React's "functional" version of sharing a complex object across components (context) requires an actual JSX wrapper to be written in angle brackets, so we are just delegating inheritance and wrapping to different syntax, not removing it.
Besides, class-based is deprecated in React these days.
[0] https://medium.com/gitconnected/functional-programming-in-typescript-18ac096bb551 https://medium.com/gitconnected/functional-programming-in-ty...
[1] https://medium.com/gitconnected/getting-started-with-web-components-lit-part-1-911aa7058e9b https://medium.com/gitconnected/getting-started-with-web-com...
- SebastianKra 2y agoIt's funny that you mention Lit, because, to me, it is a good example of why classes are the wrong abstractions for UI. My go-to example is the Reactive Controller [1]. Some of the following concerns may seem minor in this simple example, but from experience with similar class based Frameworks, I know that they significantly contribute to accidental complexity as the interface grows: - secondary state such as the timer handle pollutes the class members since the setup- and cleanup functions are separate members rather than the former returning the latter. - it doesn't handle the timeout changing. Even in this tiny example, that would require bit of a refactor. - state is declared far away from where it is actually needed. - it takes about twice as many LOCs as the same code in React. Explicit code is not necessarily bad, but even in this small example it detracts from the readability compared to the React version [2]. - we need to manually trigger the re-render rather than the app keeping track of it for us. - ...and where other Frameworks can at least argue performance since their reactive primitives are usually more fine-grained, Lit can't. Every controller can only trigger a re-render of the entire component. It might actually be worse, since there's no built-in way for memoization. I will admit that, at first glance, the class system has an universal appeal. It's familiar and does indeed seem easier to reason about as you can clearly see the relationship between events and subsequent changes. But the only reason why we turned to other abstractions in the first place, was that classes turn to spaghetti really quickly as you have to manually keep track of the exponentially increasing amount of state transitions. On a related note, I'm (genuinely) unsure if classes were a good abstraction in the first place. They come with a ton of extra keywords and concepts in every language. And in Typescript, their use-cases can usually be accomplished with functions, closures and type-inference. They work well for storing state in memory, but we don't usually need the state in memory. State is usually stored in databases, local-storage, search params etc... In-memory state is frequently used for caching purposes, and these are can be easily abstracted away. [1]: https://lit.dev/docs/composition/controllers/ https://lit.dev/docs/composition/controllers/ [2]: export function useClock(timeout: number) { const [value, setValue] = useState(new Date()) useEffect(() => { const timerId = setInterval(timeout, () => { setValue(new Date() }) return () => clearInterval(timerId) }, [timeout]) return value }