35 ms·
As others have already pointed out, it's a bit of a misconception about React, certainly not helped by it's name - it is not truly reactive. Think about all th
by ricardobeat 6y ago
As others have already pointed out, it's a bit of a misconception about React, certainly not helped by it's name - it is not truly reactive.
Think about all the ways you can trigger a re-render: either `setState`, `forceUpdate`, dispatching an event, or some other kind of update function from a state management library. It doesn't react to any kind of assignment like would happen in Vue or Svelte. They do exactly the same as your `rerender` function here, it's just nicely hidden. There will be no more of a mess of event listeners than you'd get using React.
- daveidol 6y agoSure, it doesn't react to assignment, but it still encourages the immutable data patterns of a more functional/reactive programming style. The docs for Forgo here show a lot of direct DOM manipulation and/or direct assignment to mutable data structures, which you then have to synchronize. I personally almost never have to think about these things when I build with React and treat everything as immutable / pure. Then things update according to reference inequality / shallow diffing of props. You can even update a prop at the top of the component tree and it won't re-render children that didn't actually change (and without you having to orchestrate that yourself).
- ricardobeat 6y ago> you can even update a prop at the top of the component tree and it won't re-render children that didn't actually change That's true; the upside of immutability was supposed to be more efficiency when doing reconciliation. But in reality every large React app I've ever seen re-renders entire swaths of the component tree unnecessarily due to complexity - especially now with Context, nullifying that. It seems that a whole lot of people actually prefer mutability. See the popularity of MobX, and even libraries like seamless-immutable actually have the goal of offering a mutation interface that generates immutable objects underneath. If you can have mutations and correctness, sounds like a good deal. I've been using Svelte a lot recently, and it's a breathe of fresh air to not worry about component lifecycle. On top of that, React doesn't do inequality checks unless you explicitly use PureComponent, or wrap function components in memo(), so you need a lot of manual work to actually get that benefit. It's basically the inverse of having to call `rerender` everywhere.
- lewisl9029 6y agoThe fact that mutation is more ergonomic in JS and that React isn't doing that much by default to take advantage of immutability is a fair point. But an important distinction to make is that React is actually not _able_ to take full advantage of immutability by default today in the JS ecosystem because it depends on passing around mutable JS data structures, that don't have value equality semantics outside of primitive types like strings and numbers. In the case of React wrappers in functional languages, such as ClojureScript's Om and Reagent (and probably many others, but those are the ones I'm personally familiar with), components actually have the PureComponent optimization enabled by default. This is because deep equality checking comes for free due to value equality semantics of the underlying persistent data structures offered by the language. The PureComponent optimization itself ends up becoming a much more effective global optimization in these languages, as it ends up benefiting the vast majority of use cases, whereby rerenders get optimized away as long as the _values_ getting passed around aren't changing, regardless of how or when those values are produced. Contrast that to the case with JS's mutable data structures, where the only time when PureComponent can save you from rerendering is if no references (as opposed to values) change, which is much rarer to come across in practice (in fact they change by default for every computation you make on every render), so it's something you end up having to deliberately optimize for (although the ergonomics of the tools for actually making these optimizations has come a long way since the class component days with hooks like useMemo and useCallback). This is why PureComponent is not enabled by default as a global optimization for React in JS, because a vast majority of use cases won't actually benefit from it. As such, the cost of actually checking for equality for every component ends up over-weighting the benefits of a tiny handful of potentially skipped renders.
- beders 6y agoQuietly sitting in my re-frame corner and wondering how JS developers cope with framework-churn. And, yes, reagent (used by re-frame) nicely combines pure component optimizations with react-style rendering.
- RobertKerans 6y agoI get it's a glib comment, but serious answer because the answer is "same as every other language". JS is easy to write, has a vast ecosystem, a vast number of developers using it. Subsequently there are a lot more people writing their thoughts about it on the internet. There are lots of "new" frameworks, nobody uses them, but because of language popularity the number of people writing about {shiny thing} as if it's used is relatively high compared to other languages (PHP, for example, had the same issue, if it even is an issue). 1. See {thing}, assess whether to ignore it or keep an eye on it. 2. If {thing} is brand new, wait a year or so, then go to 1. If {thing} is a few years old and/or has [possibly suddenly] gained traction and/or provides immediate, obvious and significant benefits (assessing latter being where lack of experience can cause an issue), go to 3. 3. If {thing} is only starting to gain traction, wait a year or so, then go to 2. If {thing} has gained traction and is battle tested go to 4 4. If {thing} has traction + community + libraries + docs + tutorials then same as before, but more seriously, judge whether usable. Early adopters using and writing about it are at stage 1 or 2 which could lead to stage 3 and 4. {Large company throwing resources at thing} may push it up ranking. React/Vue/Angular and probably Ember are at stage 4. Svelte possibly 3 possibly 4. React/Vue/Svelte/Ember use same underlying paradigm. Would expect a developer familiar with one to easily switch productively to another in a few weeks. Not quite much of a muchness, but close enough. Angular slightly different paradigm. Usage of everything else is so low as to be irrelevant. At first glance this is at stage 1 and is currently fairly useless. That's not a slight on the developer, just how it is. It doesn't affect any perceived "framework churn" because it will only be tried by very few developers. There may come point several years from now where it becomes useful and widely used (this seems unlikely from skimming the linked site, as it seems to provide nothing interesting, but I may be missing something), but now is not that point.
- com2kid 6y ago> You can even update a prop at the top of the component tree and it won't re-render children that didn't actually change (and without you having to orchestrate that yourself). The number of React apps that render super slowly, with visible delays when typing, is proof that it is easy to make very poorly performing react apps.
- ZephyrBlu 6y ago> They do exactly the same as your `rerender` function here, it's just nicely hidden That's the whole point. React does this for you in the background. You don't have to think about it. > There will be no more of a mess of event listeners than you'd get using React. There will be more of a mess because you have to programmatically update elements. With React, I can alter global state and every single element that uses that state gets re-rendered. That isn't possible with this framework.
- jeswin 6y agoRe-rendering for state changes is a fairly easy thing to do, if you're willing to accept something like useState/setState. It can even be done application-side (without help from the lib). Basically, just wrap all state changes in setState and re-render everytime. Now the optimization I haven't done is deciding whether a child needs to re-render when a parent re-renders. Comparing the props seems like a straightforward way to do this, so I'll probably spend some time over it today and implement it soon.
- ZephyrBlu 6y agoYep sorry, I misunderstood how your library works. I left another comment explaining what I misunderstood: https://news.ycombinator.com/item?id=25800961 https://news.ycombinator.com/item?id=25800961
- ricardobeat 6y agoYou are programatically updating elements in React, you just internalized a different set of rules (putting state in the designated buckets vs calling an update function). It is the equivalent of this: const setState = (s) => { state = s; rerender() }; Real reactivity is what you get with proxies in Vue, or a smart compiler like Svelte. > I can alter global state ... that isn't possible with this framework You'd just need to export a state object from a module, import into the components, and call rerender after any mutation. I've actually written quite a few vanilla-js apps using this structure when I don't want to bother with tooling, small pages don't need a complex reconciler. I'm not saying this is better btw - there are ergonomic concerns and different trade-offs, but the distance from this to what React does is much, much shorter than most people think. We've just been conditioned to accept its rules as 'normal': don't declare plain variables in your functions, don't mutate properties, don't use inline functions as props, don't rely on previous state object for updates, and so on... step outside the box and you'll get a mess too. This library is just a smaller, different shape box.