Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm a big fan of Svelte. I've raved about their documentation before, but it bears repeating: this should be the gold standard. You can read it all in a day. There are examples to follow right next to the documentation.

Svelte is both succinct and powerful. I find this in contrast to React which is often baffling and incoherent. I say this as someone that has used React professionally for 6 years. They've changed their mind at least 3 times on the API and none of it fits together today. Hooks and classes don't mix, lifecycle methods are still out there and just as confusing today as they were years ago. Mixing state and functions. It's just a horrible bag of half-baked bad ideas. And it's not even batteries included.

Svelte has it all built-in. It has the equivalent of CSS modules. It has global reactive state and an incredibly simple state protocol that seems almost stupid if you're coming from Redux. You step out of your daze and realize you don't need all the rituals and boilerplate. The things I've seen built on top of that simple protocol can be incredible. It's not magic. It's just JavaScript.

I dare say that Svelte is a joy. But I hesitate to even leave this comment here. Because I know the architecture astronauts are listening, eager to sink their claws into this simple elegant new thing and fill up their Github profiles with soon-to-be abandonware cruft which they will use to pad out article after Medium article which will all pour down upon Hacker News like a shit typhoon. Prodding us to join their cult of Svelte+RxJS. Or Svelte Sagas. Or their random dogma they toss into a giant bucket labeled "Svelte best practices." And, of course, "Ten ways you are doing Svelte wrong."

I might be a little bit cynical.



But I wish new frameworks stayed away from inventing new language syntax. Not only is it a cognitive burden on programmers, it throws all the tooling off.

From Svelte: {#each cats as { id, name }, i}

JavaScript already has facility for loops and mapping, and relying on that will automatically get you tooling/IDE support. React handles this aspect quite well, and to me that's a point in favor of React.

I do agree with your post - especially on hooks being a step backward.


I agree that gratuitous syntax differences are tiring, but in this case, there's actually a very good reason why it's not just using JS. When it comes to reactive systems, you need to be able to statically analyze control flow structures in order to compile to efficient code. In JS, a for loop is a loop, but so is array.map, Object.keys and someLib.each. The loop could be hidden three layers deep in a higher-order function composition from some third party library, it could be tail call recursion, etc. Dealing with this sort of complexity when writing optimizing compilers is very very hard, compared to coming up with dedicated loop syntax, because at any point it's possible there's a value of polymorphic type, a Proxy, a getter/setter side effect or some other crazy JS shenanigan going on.

This is why, for example, Solid.js does control flow through <For /> and <Show /> components instead of map/ternaries even though it uses JSX.


I understand why they did it, but there are alternatives.

Such as:

   import * from "svelte";

   // ...omitted for brevity.
   {
     svelte.each(cats, ({ id, name }) => <p>Hello {name}</p>)
   }
   // ...omitted
This is easy to parse and transform, while being fully within JS.


Until you try to do something svelte doesn't understand. Then it'd silently break. Templates are powerful _because_ of the restrictions they place, not in spite of them.

I think a much better recommendation would be an existing template language, iff svelte could understand it with perfect parity.

I hate being handed normal syntax to use when not all of it is normal, or when using it has different semantics than the syntax usually carries.


I was saying elsewhere on the thread - I am not suggesting that each should be turned into a runtime call. Instead, 'svelte.each()' callsites are easy to identify in the AST and transform in the compiler.

So the errors remain compile-time, not run-time.


The danger is that a developer will use `svelte.each()`, thinking it uses the same rules as normal JS syntax, but it turns out Svelte applies its own rules which _are_ slightly different (hypothetically).

So the developer must remember a new rule: "JS rules when calling foo.each(), Svelte rules when calling svelte.each()". A little harder to remember. Having a unique non-JS syntax makes the distinction obvious.

(Just playing Devil's Advocate here)


That's a pretty reasonable argument and I believe a big part of what makes hooks somewhat complex since they look like regular Javascript but can behave differently.


FWIW, I did a mini-study a while back about the different possible syntaxes. It turns out there's more than meets the eye wrt what control flow structures need to do, and there are also DX reasons why the dedicated syntax might be more desirable: when you consider all permutations of loop flavors - w/ else clauses, keyed, exposing index, etc - the DSL consistently came out on top in terms of succinctness and readability (for an average developer familiar w/ algol-like syntax).

There are also technical reasons why `svelte.each` would be problematic, namely the fact that it is a compile-time concept which does not necessarily compile correctly if you move the call into a library, unless you have an extremely sophisticated compiler (aka: a slow compiler)


> There are also technical reasons why `svelte.each` would be problematic...

I am not suggesting that the svelte.each() call be moved into a library; I'm proposing that the callsite is trivial to identify in the AST. Svelte compiler could then do the same thing that it does now.


Yes, parsing is trivial, but compiling (in the traditional sense, not the transpilation sense) is a different story. The other sibling comment nails it.

Grammar enforces where a grammar construct is allowed to exist. A custom grammar can be very restrictive (which it is, to great effect, in Svelte's case).

If we reuse JS grammar, then that comes with expectations of what should semantically work. For example something as simple as `$ = svelte.each` might evade a not-sufficiently-smart compiler. Or maybe `console.log(svelte.each(...))` might mis-compile because nobody ever thought to handle that case.

Having used systems with compile-time grammar constructs that look like runtime constructs, I can tell you that having your expectations about semantics being changed from under your feet can be a very frustrating experience.


You're right about it being complex (my experience [1]), but such work is within scope for what's perhaps a central design decision for a library. Yes there'll be bugs, but it'll stabilize over time.

Just to be clear, I am NOT saying that Svelte needed to do this. But merely suggesting options for discussion and learning.

[1]: https://github.com/jeswin-unmaintained/isotropy-ast-analyzer... - Here's for instance, some code I wrote for analyzing a JS sort expression. You'd think it'd take just a few hours, until you get to it. Btw, it uses an AST analysis framework I wrote called chimpanzee - it has only one user though. :) https://github.com/jeswin/chimpanzee


To deal with the issues they're talking about, you usually end up encumbering `svelte.each` with limitations such that it only looks like Javascript superficially.

In such a case, I think it's less confusing at the end of the day to just have a custom DSL for looping so that there's no clashing with its list of arbitrary limitations.


I think you are persistently suggesting something to someone who knows more than you, without taking the proper time beforehand to understand the problem space.


I do believe I understand the problem space well enough to comment on it - both AST analysis and frontend frameworks. My comment above also included a clarification that I was not suggesting that this be turned into a runtime call. Just presenting an entirely subjective viewpoint (of avoiding new language syntax), but one that many people share.


> Dealing with this sort of complexity when writing optimizing compilers is very very hard

Which is why we use JS and allow V8/SpiderMonkey/JSC to do it for us :)


Javascript was originally supposed to be a Lisp. In this alternative universe, there would be no need for Svelte. For a portal into this universe, see Clojurescript's Mr. Clean [0].

[0]: https://bitbucket.org/sonwh98/mr-clean/src/master/


I was with you on this topic, and I have rants about this elsewhere.

But with Svelte 3 I actually agree with their choice now:

1. The extra templating syntax is rather small and concise. And explicit.

- There are very few directives, and they follow the same rules: `{# start block }{: alternative branch}{/end block}`

- external data that comes from Javascript is always `{data}`

- properties of html components that can be bound are always `prop:name|modifiers={data}`

This is in contrast to, say, Vue, where the syntax can never decide where it's going.

And compared to React, this isn't Javascript either if we think about it:

   {
     svelte.each(cats, ({ id, name }) => <p>Hello {name}</p>)
   }
That's a specific extension that compiles to Javascript

2. Your work becomes MVC-ish

Your template/html becomes "I have some data, let's display it". And since the template syntax doesn't allow arbitrary logic, you end up collocating transformations of your data with the code that's fetching it. Instead of doing some weird logic inside the template like `data.map.filter.map`

3. But to each their own :)

What really turned me towards Svelte is going through the tutorial and then trying it. It really is good :)


As I noted in another comment, what we’re really dealing with in compiled templates are reader macros. And unfortunately, reader macros break composability.


I think many people adopted React because Facebook was behind it, and using it in production, the ecosystem is huge, there is a react- package for everything you can image, there is also react-native, I don't like it, but there it is, you can reuse the knowledge to build native mobile apps.

Now Svelte, I haven't been following, but I think the creators are working in what's going to be next and even better framework[1], to your point of things in Svelte not changing as much as in React, maybe it just a matter of time. Here is the video I had in my bookmarks for a while, I still couldn't make the time to watch, so I hope my comment is not too far from reality.

[1]https://www.youtube.com/watch?v=qSfdtmcZ4d0&t=875s


It's so boringly cynical to suggest that people use something because they're lemmings rather than any of the great reasons to use something.

Go watch the original React debut talk and ask yourself if React had/has anything going for it beyond Facebook's backing. I know I, and most developers I know, dropped Backbone/Knockout/whatever instantly to use React because it was so obviously better.

Now that unidirectional flow is the state of the art, the difference between the main frameworks just isn't that big. You gain a few things here, lose a few things there, and write a solution that is similar to what you would have written with the other frameworks.


> I know I, and most developers I know, dropped Backbone/Knockout/whatever instantly to use React because it was so obviously better.

You skipped a huge step. There was angular before react. Which was horribly bloated and over complicated. People wanted something simpler. React, with it's facebook clout won in the end.


Something simpler: Vue

Something more simpler: Svelte

Just try it and give it a chance.


Both the uni-directional data flow and virtual dom were not exactly new ideas when React/Flow came out. There were other libraries/frameworks playing with similar concepts at the time. Half a dozen new ones appeared in 2014. React won the lion's share of developer adoption.

I personally heard that 'objectively better' line incessantly from 2015 onwards, with 'it has the largest community' always being a top highlight. Facebook's backing and the celebrities that developed in the JS community around the time certainly played a part in it.


I went to one of FB's early internal meetups about React and I was initially skeptical of JSX but very excited by what it offered.

I was working at Groupon and using Backbone at the time and found nesting components to be a major hassle. We used a framework called Thorax on top of Backbone, which helped but still fell far short of React's convenience.


> to suggest that people use something because they're lemmings

That's not what I intended to say, of course that's not the only reason people choose React, but I think they are valid reasons to help you decide.

For example let's say two libraries are technically different but equivalent productive and nifty, choosing the one that has a bigger ecosystem is a totally valid choice.

Many people had to sell React to their bosses, and the fact that there was a presentation by Facebook, helped a lot, I don't see how stating the obvious is calling lemmings to anyone.

At the end of the day, it depends on your goals and motivations, I can't talk for everyone, I was actually saying some of the reasons that helped me decide on choosing React.


I don’t think any of your arguments in favour of react are sufficient. JQuery had a huge number of libraries and could be used to make websites that worked. Angular was backed by Google who generally have more clout than Facebook. I think most comparisons would find that jQuery does not solve the same problems and that angular resembles the kind of steaming brown thing one might find behind a cow—and that’s before you consider backwards compatibility.

I would argue that react has some particular merits (for three the whole vdom based architecture, using jsx, and unidirectional data flow), that it was the first (widely known) framework with those merits, and that it has generally been backwards compatible or only required simple changes. I think these do a better job of explaining why react became popular and inertia explains why it is still popular.


Your counter points don’t check out too much though?

> jQuery

Just not possible to compose, which makes full applications difficult. No answers for state management or such either, completely a different scope than frameworks

> Google more clout than FB

In some domains sure, but I’ve never understood how people don’t think FB are masters of UI. There is probably no org with more UI clout than FB, they built their own insanely adopted library after all while Google can barely force their own engineers to use Angular

React is also unquestionably the most JavaScript of the libraries, a component’s markup is such a thin abstraction around an object and maps perfectly to DOM trees and concepts, classes or functions or hooks are all using native JS concepts, explicitly typed typescript and react genuinely eliminates the need for all simple testing plus makes for a streamlined developer experience, and its concepts of lifecycles and composability introduce complexity but in my opinion in a clearly delineated and extremely powerful way

Also, as always I have to note this, the churn argument is completely overblown wrt React, each way of writing code still works or compiles, conceptually the lifecycle and state management never changed just its syntax, and npm has old versions for a reason. I run 2016 code in production today as an internal application for engineers, and I’ve seamlessly updated webpack and module versions while keeping the same code syntax.


Oddly, despite the immense resources that Facebook has available, Facebook in a browser is slow and glitchy, especially after the most recent redesign.


I can't say I share that experience at all - I make quite an effort to avoid installing their invasive apps, always using the browser - but it's an interesting point


writing react apps in a proper way is hard, very hard. plenty of companies out there big and small can't do it. once you've a professional react dev, you easily recognize the react apps due to the subtle bugs. makes me miss my old team, where our big react app was actually performant.


Can you speak to these bugs? I personally don't agree that React apps impart any standard class of bugs, but maybe that's because Redux is actually the source of all these issues and I've avoided redux like the plague it is


example app: airbnb when you get messages. click a message. and you'll see it will still have an indicator that you've a message, when you've none. airbnb guys are some of the best react guys out there even released open source libraries like enyzme etc. fact is no one can ever get the react thing right. don't get me started on facebook. plenty of bugs in their new app. But for some reason, instagram web is polished.


nice point on pointing out the redux part. yeah most times it's the point of bugs - state mismatch etc.


If a framework/library is very hard to use correctly - even for people who are not only experts, but contributors - then that's a huge red flag against it.


Sure, but if massive amounts of people disagree with that take and think the library is strong, intuitive, and best-in-class, maybe someone is just struggling with understanding the structure of the library


> that it was the first (widely known) framework with those merits

Yep, and my interpretation is that, that (the widely known part) happened because it was backed by Instagram first (if I recall correctly) and then Facebook.

And not to invalidate your point but to add another speculation on why React became more popular...

Yes, Angular was backed by Google, but not used in production in massively successful product as Facebook, or Instagram, and I remember also about writing Directives, Services and it wasn't very inviting for third party packages.

When react came out, I remember the selling point was "it's not a framework, it's a library", "it's the V of MVC" and I think that strategy also helped to let the community create all the other pieces, and long term have a richer ecosystem.


The main reason people started using React is the JSX implementation in React at the time was very innovative. Actually many people working with Rihno in 2006 has talked about using JSX as templating system. FB is just the first one did it. However, now days there are plenty other less bloated front end frame work such as svelte, vue, mithrill that is more easy to use and have JSX support as well. There is really no reason to use React now days.


It took a month to teach angular and a year to become proficient. Knockout or backbone + handlebars were similarly large commitments. React took a day or two to learn and less than a a month to completely master.

I also hear about “react doesn’t have one way of doing thing’s built in”, but it wouldn’t have been as successful if it had. It ate up other frameworks because it was so easy to integrate.

Need more performance in your angular app? Just add an ng-react component. Have an extensive backbone project? You can just gradually swap in react to replace your mustache templates and leave backbone alone. Have a jQuery widget that’s getting hard to maintain? Change to React and the rest of the page renders on the server like it always did.

And of course, you could greenfield with flux, rxJS, or whatever other thing worked for your company. But if they hadn’t been flexible from the start, there wouldn’t have been room to create and test things like reactive programming, redux, mobx , etc


How is Svelte "just JavaScript" when it uses custom templates and file types?


I feel like this "just javascript" trope really needs to die. JSX is not "Just Javascript", and magically reactive `foo = bar` assigments are not "Just Javascript". But frankly, that doesn't really matter one bit anyways; it's fairly nitpicky to object to different control flow syntaxes, when at the end of the day you're just rendering data from a request to screen. I'm sure not many people would be willing to argue that throwing promises (as react suspense supposedly does) is a holy grail of frontend development, even though it is "just javascript".


> JSX is not "Just Javascript"

It's very thin syntactic sugar over a function call. It has a very simple 1:1 mapping to the output code, as opposed to "magically reactive `foo = bar`.

> I'm sure not many people would be willing to argue that throwing promises (as react suspense supposedly does) is a holy grail of frontend development, even though it is "just javascript".

I'll give you that hooks and suspense are straying further from normal js because they don't behave like normal functions do and have special rules for being called; hooks are a DSL for encoding incremental computations into js, and suspense is just the react team fawning over algebraic effects/delimited continuations and trying to reproduce them in js.

But then again, all of these can be defined in normal JS code as opposed to a DSL which compiles to who knows what, so all the rules applying to normal JS and its tooling apply to them.


I should also explain what I mean by "thin syntactic sugar": JSX is a local transformation which doesn't need any external context to be translated to plain JS. `<div className="greeting">Hello</div>` will always compile to `React.createElement('div', { greeting: "hello" }, "Hello")` no matter what; in Svelte, `count += 1` will output different code based on its context because it will compile the whole component as a single unit.


> compiles to who knows what

You can easily read the compiled Svelte output and see how each piece of template is wired to the state. There is very little cruft in it, and no real runtime library to speak of.

The debugging experience (not that I have needed it much) is light years ahead compared to going through React's internals.


Yeah, but it's still a DSL and that means that I can't be sure that everything I can normally do in JS is valid there, and external tooling won't be able to make sense of it without additional work.


Those sounds like very abstract concerns - I haven't had any issues on those lines using Svelte for years now. The $: syntax is actually valid JS (labels) so standard JS tooling should always be able to parse it.


> It's very thin syntactic sugar over a function call

Actually, it's not. It's a set of AST nodes. What they compile to is entirely implementation-specific. Look at Inferno.js or Solid.js compiled code for example; it looks nothing like simple function calls. Although obscure, there are also other spin-off ideas floating around like compiling to math expressions or to file system APIs. Even within the scope of React, the idea of allowing configuration for optionally compiling to `h` instead of `React.createElement` for minification purposes has been brought up (and is doable in React proper in user space, and out of box with Preact).

The idea of adding JSX to JS got brought up before and it got shot down precisely because the compilation semantics of JSX are not formally specified.

> all of these can be defined in normal JS code as opposed to a DSL

Right, but my point is that "just javascript" is not a good guiding light if the goal is implementing a pit of success. The crank.js blog post talks about how its author thinks React has gone off the rails pursuing some notion of purity. DSLs are not automatically bad things. I've mentioned Solid.js before and it has a component-based DSL for control flow, and honestly that looks quite reasonable. At some point if one jumps the shark, so to speak, and starts making uncomfortable contortions to stay within the confines of "just javascript" and avoid DSLs at all costs, that amounts to leaving a useful tool unused at the table, where it could have been effective. "When all you have is a hammer", etc.


> It's a set of AST nodes.

Ok, but you could make the same point about plain JS as in Svelte. I haven't looked into it too much, but from the readme Solid.js looks more like a compiler than a library, so whatever it outputs when it sees JSX doesn't have much to do with what JSX is usually used for, imo. I've only ever seen it used as syntactic sugar for function calls, be it `React.createElement` or `h` or `jsx`.

> At some point if one jumps the shark, so to speak, and starts making uncomfortable contortions to stay within the confines of "just javascript" and avoid DSLs at all costs, that amounts to leaving a useful tool unused at the table, where it could have been effective.

Personally I find it much more likely that I'll have to bend over backwards when I'm dealing with a DSL rather than just plain code, because the DSL will be really well optimized for one usecase, but has omitted another usecase that I will need at some point, and then I'll have to find some hack to accomodate the DSL rather than just add that one line of code that I could've used if it was just Plain Code.

The downside is that some other things will look kind of awkward and since you're now dealing with a turing-complete language you'll lose analizability, but IMO for UIs those are worth losing if I can just use plain code.


> Personally I find it much more likely that I'll have to bend over backwards when I'm dealing with a DSL rather than just plain code

I think this is cherrypicking at generalities. It's just as easy to run into a wall with "regular code" because some API doesn't provide what you need. Conversely, DSLs often have escape hatches (e.g. https://www.smarty.net/docsv2/en/language.function.php.tpl)

DSLs are useful sometimes. Heck, the entire web is built on top of DSLs: HTML, CSS, SQL, even JSX. I agree that there are valid criticisms to be made about specific implementations of specific DSLs, but I don't agree that those criticisms are generalizable to the concept of DSLs as a tool in a framework designer's arsenal.


I wasn't criticizing DSLs in general, they're great, but in the specific case of web development I prefer React's approach over using a DSL like most other frameworks.


where do I read about this throwing promises thing?


The crank.js intro blog post is a good place to start[0]

[0] https://crank.js.org/blog/introducing-crank


Insightful read, thank you.


Actually React can stake a better claim to being "just JavaScript" than Svelte. Once you know what JSX compiles to (the rules are fairly basic), React does become "just JavaScript".

That's not the case with Vue, Angular or Svelte. There's framework specific syntax that you need to learn. Eg: '{#each things as thing}' from Svelte's documentation.


Svelte itself is a compiler: It compiles the `.svelte` files into (readable-ish) vanilla JavaScript that runs directly in the browser.


X is a Y that Z things in to vanilla js


It's "just javascript" because if you want to modify anything and have it re-render, it's `let counter = 0; counter++`, not `const [counter, setCounter] = useState(0); setCounter(counter + 1); `. Of course there's template and all, but for regular logic, you don't have to fiddle around abstractions.


You think that it‘s just reassignment in svelte? I don‘t think so.

Counter in this example is likely a proxy object that knows when it‘s changed and tells svelte to re-render.

It‘s also not immutable, which can cause very confusing interactions in global state.


I've only dabbled with Svelte, but I agree that it looks like an excellent framework, in itself. Powerful abstractions, succinct and approachable syntax, and it compiles down to a truly compact output. (Not the usual only a few hundred kilobytes when gzipped.)

I ended up not using it though, as the surrounding ecosystem just isn't there. There are two different material design frameworks out there for Svelte, neither of which I could get to work. I ended up opting for Angular+Angular Material, which worked out of the box.


Neither agree or disagree, but just want to say that's exactly how I felt about Angular when React first came out. It wasn't much of a "framework" at all, just an easy way to render onto the DOM from js.

I very much like the idea of compiling code to make direct DOM mutating managable. A very powerful idea regardless of which syntax you end up going with. I wish their website talked more about this instead of having a React comparison on every page.


This comment makes me want to seriously give Svelte a try. I've browsed the docs and it looks really cool, I've always just held back because I feel like I am juggling enough JavaScript libraries in my head already and React has been great.


FWIW, Svelte has a very easy learning curve.


I did some React development some years ago, and was glad to move away from it because of the ridiculous churn in the ecosystem. It was like building on top of quicksand. At the time, I thought it was because React was new, and new stuff tends to have churn because people are just figuring out the optimum patterns and false starts are to be expected. When I look into React years later, the churn is still going on, which perhaps is a warning sign it just wasn't well thought through to begin with, or that the ecosystem has been captured by architecture astronauts on a lifelong quest for some kind of pure ideal rather than usability and stability.


I agree with your impressions. When I first started working with react professionally one year ago I was thinking I was dumb for not being able to find the logic behind the different moving parts. Now I know that there's none.


IMO, Svelte’s biggest issue is it didn’t come out of FAANG.


biggest issue of Svelte (and vue and others) is that mutable state is marketed as a feature. If you don't like mutable state anyway then it just seems like an inferior way of writing code.


You can't get away from mutable state. Redux, for example, just hides the big `state = newState` mutation but it's still very much there. When a library/framework uses mutable state, it's not that they're saying immutability is an anti-feature. They're just being pragmatic in the sense that mutation has to happen anyways and they consider explicit to be better than implicit. (With that said, some people do argue that immutable JS is in fact an anti-pattern because JS doesn't really lend itself to idiomatic performant immutability in the first place and emulating it as an abstraction adds a lot of unwanted complexity)

IMHO, it's a disservice to yourself to just blindly drink the immutable koolaid without understanding the very real drawbacks it comes with in JS-land. There's a great deal of gray area where explicit mutation is perfectly adequate in ways that overzealous immutability might be counterproductive.


you're arguing based on a very mechanical understanding of why immutable state is important. Immutability is just a solution to the actual goal which is controlled side effect as someone put in the other comment.

Given a side effect (a piece of data is mutated), I need to know what code caused it and when. When you casually throw assign statements everywhere that question becomes really hard to answer.


Not necessarily. Discoverability is a function of colocation, not of immutability. One can write convoluted Redux monstrosities spanning a multitude of files where it's difficult to mentally follow how a dispatched action translates into state deltas (potentially because of too much higher-order abstractions, but also because one action may affect multiple reducers, and that in turn may affect a multitude of React tree nodes because Context or whatever). Svelte reactivity generally only staying within a single file (with some exceptions) is one approach to align system limitations with "pit of success" in a way that happens to use explicit mutation idioms.


> Discoverability is a function of colocation, not of immutability

That's one way to do it, tying discoverability to coding convention (which is usually how collocation is enforced), as opposed to being an inherent property of the code.


could you stop saying redux, in my other comment I said the solution could be anything from react's setState to old-style encapsulation.

The point is, it's kind of odd that someone'd put mutating states in their tutorial proudly as a "feature". It's a thing that you do very conservatively at best.


> it's kind of odd that someone'd put mutating states in their tutorial proudly as a "feature"

Mutating state is actually the de-facto standard across most of the industry. Look at Vue or iOS or Android or Unity or Rails or J2EE... People literally use ORMs to make things more mutable than SQL.

Yes, you can use React setState, but surely it's not lost on you that this is wrapping over a lot of mutable operations too? Worth mentioning as well that setState semantics have some amount of complexity that is attributable to mutability leaking out of the immutability abstraction (e.g. the callback argument, what happens when things like multiple calls to setState occur synchronously, etc). This is the "curse of abstraction" that comes when you are trying to implement semantics that don't exist natively and the abstraction themselves have semantic weaknesses due to the chicken-and-egg problem of the required semantics not existing natively.


again with the mechanical definition of mutability. Ok "controlled" is the word, as I mentioned in other comment state encapsulation (which ORM is) is another solution for this.


These giant monstrosities are really easy to avoid. Redux Actions make locating a state change a breeze. I have worked on giant applications that did not use a redux-like approach to state and it was a horrendous mess.


FWIW, I see a lot of codebases at work (I maintain a large org-wide monorepo), and you'd be surprised at how daunting real world codebases can get. I agree that it's relatively easier to keep a codebase clean when the number of owners is small, but conversely, from my experience, when a codebase has multiple owners, keeping things organized can definitely be a challenge (in some cases I've seen, multiple teams owning overlapping sets of the codebase...)

I've seen codebases with messy redux and codebases with messy non-redux architectures, and conversely also clean codebases with both types of architecture. There really is no silver bullet technology. The "you can write cobol in any language" thing is always going to be a looming plague.


I think it's easy to get into a mess as an applications complexity increases regardless of which state management approach one chooses. Every paradigm has a trade off.


If you mutate through the vueX store then the debugger will give you a commit history of mutations and an ability to revert them individually.


Yes.

To be fair, after looking how the whole Redux story went, I think the mainstream simply wasn't ready for immutable state.


When people not use something, they are not ready for it?

I think they simply don't need it.


Yeah, I feel for dirty admitting this in this forum, but I still use React & MobX for state management. I get to use simple classes with observable state management. Works just dandy for me.


Redux was shit. It made apps less comprehensible and less performant.

Immutable state isn't really a great idea for stateful applications, and UI development is an almost purely stateful activity. It can easily be said that any UI is fundamentally a state machine...the state of your UI defines the set of actions that are available to it, and the actions taken define the future state of the UI. This is not just true for web UIs, but all UIs. It is just as true for your blender or transmission lever as it is for your react app. And being a stateful problem, you're far more likely to have to change state than you'll have to change how that state is rendered. This puts redux-style solutions squarely on the wrong side of the expression problem. And the fact that your state is essentially a global variable, using it means you spend vast amounts of time trying to thread constantly changing data types through intricately nested pure functions, and it just fucking sucks.

I'm generally a pure functional programming kind of nerd, but when it comes to difficult inherently stateful programming problems like UI dev, game programming, or simulations, nothing is better than plain old encapsulated state via classes (or maybe actors). Anybody who advocates for pure functional approaches to these types of problems has lost the plot.


> It can easily be said that any UI is fundamentally a state machine

This doesn't make sense to me as a criticism of Redux. Redux is a giant state machine. That's all it is. Actions are transitions and the store is the current state. The state transition table is the reducer.

The Redux architecture (and the Elm architecture that inspired it) is about the purest expression of a state machine you're likely to find in any architecture. The fact that a UI is just a giant state machine is the whole reason these architectures were created in the first place.

Redux is tricky and boilerplate-y because of some interactions with React, because it doesn't come with a built-in mechanism for handling interactions with the world "outside" the UI (e.g. interactions with the backend), and because JS doesn't have facilities for immutability out of the box and rather you must bolt on post-hoc solutions.


The problem with Redux is two fold:

1. The datastore is a massive global. This already brings to it many of the pitfalls that have caused programmers everywhere to avoid global variables like the plague. But in addition to that, for incredibly complex apps, it is a massive burden to maintain all of your state in one place, without any ability to encapsulate or localize trivial local states. Why do I need a global state tree to determine which option is selected in my select dropdown? Why should I bundle the varying hyperlocalized implications of onChange actions vs onSelect actions with the business implications of things like payment submission states? Why does the state of one button for basic user A have to be bundled in the same data structure as an input element three tabs over, two levels deeper, meant for admin user B with privileged access?

2. Robbed of the concept of benign localized state, all state transitions must be weaved through the entire complex functional tree that renders it. Small refactors of your UI, like moving a widget from one place to a different location in your application "tree", involve not just refactoring the component which renders the widget, but every single component that it passes through, to reroute the data to the right location. It is extremely high touch refactoring, exacerbated by javascript's dynamic nature which is already hard to refactor, and Redux's inability to play nice with static typing tools like Typescript.

Redux's bad ideas do not come from the fact that it models a state machine, it comes from the fact that it models it poorly and forces you into using a giant state machine, intricately threaded and tightly coupled throughout your entire application, when smaller state machines are easier to understand and easier to compose.

Luckily, there is another programming construct that allows you to easily model state machines, and allows you to build them arbitrarily large or small to meet your demands, and allows you to encapsulate data and actions extremely well so that state and associated actions do not leak. They're called classes.


Note that we have _always_ advised that you should avoid putting literally every piece of state into the Redux store, and we do _strongly_ encourage keeping local state in components:

- https://redux.js.org/faq/organizing-state#do-i-have-to-put-a...

- https://redux.js.org/style-guide/style-guide#evaluate-where-...

- https://redux.js.org/tutorials/essentials/part-2-app-structu...


Which goes to the point that redux is not perfect and has its own downsides. I generally take the simplest solution to solving a problem and favor readability over abstraction whenever possible.


> The datastore is a massive global.

A single global state machine and a bunch of small state machines can be losslessly transformed from one to the other. And indeed Redux offers tooling to transform from one to the other depending on preference (this is the Redux Toolkit).

And indeed in that world they don't have to be bundled together. You can have separate state machines for different parts of the page.

> Robbed of the concept of benign localized state, all state transitions must be weaved through the entire complex functional tree that renders it.

As you say, this is really just a specialization of 1 right rather than a separate problem?

> They're called classes.

Classes of course can model state machines since any Turing complete style of programming can model state machines. However, they are significantly different from the classic representation of state machines in that the important part of representing state machines is that you can inspect their state. Classes are meant to be opaque; as you say their encapsulation is a feature.

But their opaqueness prevents the usual state machine composition, which is to link different state machines together based on the states they are currently in. Whether or not that's a good thing depends on the circumstances, but they make it painful when you really do want to represent things as a state machine proper, and not simply as a stateful component. And to the extent that you want a UI to be a state machine, that's a bad thing.

Of course not all parts of your UI should be a state machine, especially things that involve continuous states rather than discrete ones. For truly mind-numbingly benign stateful details (such as which frame a button should be in while performing an animated transition from one color to another) you can just put it directly in the React component and ignore the store altogether, and that's definitely where you really don't want explicit state machines, but rather encapsulated black boxes that are stateless from the perspective of the overall system (which is effectively what a component-based/class-based system looks like when interacting with a state machine).


> the important part of representing state machines is that you can inspect their state

Why? Is that because you need to know if a transition is valid for a given state? Do you have a citation for this?

> Classes are meant to be opaque; as you say their encapsulation is a feature.

This is true, but in practice, people do expose things in classes. I regularly implement state machines in classes as immutable builders.

> But their opaqueness prevents the usual state machine composition.

Not sure what you're refering to by this. Sounds like it's based on a specific implementation. I'm sure there are patterns that could help with this.


> I'm sure there are patterns that could help with this.

Indeed there are. Again any Turing complete language can do anything another language can with a sufficient dose of design patterns (in the limit design patterns just recreate another language). So everything I say about "classes" and "state machines" needs to be taken as talking about level of effort not possible vs. impossible, since the former, being Turing complete in most cases, can always model the latter.

But to return to the meat of your questions:

> Why? Is that because you need to know if a transition is valid for a given state?... Not sure what you're refering to by this.

In a manner of speaking yes this is about validity of transitions, but it only shows up when you're making a bigger state machine from smaller ones.

What I meant by "state machine composition" and "important part of representing state machines is that you can inspect their state" relates to the combinatorial explosion of states that occurs when you build a larger state machine from smaller state machines.

When you combine state machines naively you get a new state machine that is the combination of all its child states (the n-tuple of all the child states). These usually (but not always) are not all valid states at the parent state level. That is usually, at the parent state level, only some subset of the combination of every possible child state is a valid overall state.

This means, if you're thinking of things purely as state machines all the way down, you don't want your child state machines to be black boxes. Instead, you want to be able to form relationships between the different child states to be able to constrain them in different ways. In a statically typed language with algebraic data types this might show up as various different sum types that are subsets of tuples. In a language without sum types this often ends up being basically the visitor pattern. In a dynamically typed language this might show up as various assertions about the overall n-tuple. Either way, you need some way to "open up" the child states to inspection by the parent state.

Now sometimes, your parent state truly is the n-tuple of all its child states, i.e. the child state can be any state at all and this is still a valid parent state. At the UI level, this is usually true for anything a user would be unlikely to care about if the page were to refresh and that state was reset, for example the state that governs the animation of a flashing button, or a drop-down menu being open or closed. This is what I meant when I said "black boxes that are stateless from the perspective of the overall system." From the parent system's perspective, if the child component is a black box, you could substitute that child component with a completely stateless placeholder (e.g. a static button) and the overall system would not be in an incorrect state.

And it is precisely these places where it is most convenient to use opaque child states to model things.

However, most "significant" things in a UI are things where we do care about constraining the n-tuple of child states to a subset. We often want certain parts of the UI to gate other parts of a UI (e.g. greying out certain parts of a UI), or want certain actions in one part of the UI to cascade in a specific way across the rest of the UI.

Don't get me wrong, getting back to the beginning of my reply, I'm by no means saying that this is impossible with opaque classes. After all there have been people making perfectly functional UIs with opaque classes for a long long time. It's merely more annoying and bug-prone.

If all your child states are opaque, then all this subsetting of valid states is implicit in control flow rather than explicit in data definitions. And as Fred Brooks put it: "Show me your flowchart [control flow] and conceal your tables [data definitions], and I shall continue to be mystified. Show me your tables, and I won't usually need your flowchart; it'll be obvious."

I'm not sure what you would want from a citation? Somebody other than me saying that the important part of representing state machines is being able to inspect their state? Would you accept prior art? Languages that are explicitly built to model state machines, such as TLA+, generally expose the state explicitly by default and build all their reasoning facilities around manipulating the state directly (TLA+ is indeed generally not an executable language, but there aren't many executable languages I can think of at the moment that really go all-in on making everything a state machine like TLA+ does and so aren't great illustrations of what pure state machines are like; Elm does this as well, but Elm and Redux are the same core approach so it doesn't really count in a discussion about Redux).


> Redux is the purest expression of a state machine possible

Are you sure "pure" is the right word? Last I checked redux very proudly incorporates a certain event-sourcing something idea in it. It's definitely not a "just state machine" library. More like in KFC when you order something, they always make sure that you get their sugar water as well.


What do you mean by "a certain event-sourcing something idea?"

I really do mean "pure." That doesn't mean that Redux doesn't provide other facilities on top, such as React interop, error-handling, logging, etc. But if you don't need any of that and you use the core of Redux, it really is just a state machine representation.

Let's write out the classic finite state machine representation of a locked/unlocked item.

  States: Locked, Unlocked

  State transition table:
  
  Current State | Transition | Next State
  ---------------------------------------
  Locked        | Lock       | Locked
  Unlocked      | Lock       | Locked
  Locked        | Unlock     | Unlocked
  Unlocked      | Unlock     | Unlocked

  Initial State: Unlocked
That's a textbook definition of an FSM.

This is the equivalent Redux code.

  import { createStore } from 'redux';

  const initialState = 'Unlocked';
  
  const reducer = (currentState, transition) => {
    if (currentState === 'Locked' && transition === 'Lock') {
      return 'Locked';
    } else if (currentState === 'Locked' && transition === 'Unlock') {
      return 'Unlocked';
    } else if (currentState === 'Unlocked' && transition === 'Lock') {
      return 'Locked';
    } else if (currentState === 'Unlocked' && transition === 'Unlock') {
      return 'Unlocked';
    }
  };
  
  const store = createStore(reducer, initialState);

  // We're done! Now we can play with our state machine

  console.log(store.getState()); // 'Unlocked'

  store.dispatch('Lock');
  console.log(store.getState()); // 'Locked'

  store.dispatch('Lock');
  console.log(store.getState()); // 'Locked'

  store.dispatch('Unlock');
  console.log(store.getState()); // 'Unlocked'
That's it. That's Redux. This is exactly a 1-to-1 translation of the FSM. I don't see how it could be any more direct (at least in JS). Everything else in Redux is optional.


If you think that's the simplest you could get, more power to you. I personally think your example is convoluted for such a simple example, but that's just me.

However, I should point out something that is not actually trivial about your code, by proposing a refactor: your FSM adequately models a car lock button interface, but not the lock itself. If we are modeling the lock, you have two invalid transitions...because it is impossible to lock an already-locked lock, and it is impossible to unlock an already-unlocked lock.

Classes actually shine quite well here.

    class On {
      constructor(){
        console.log('turned on')
      }
      turnOff(){
        console.log('turning off...')
        return new Off();
      }
    }
    class Off {
      constructor(){
        console.log('turned off')
      }
      turnOn(){
        console.log('turning on...')
        return new On();
      }
    }

    const toggle = new On();
    toggle.turnOff().turnOn().turnOff().turnOff()
    //     ^ cool,    ^ cool, ^ cool.   ^ oh shit, typescript really doesn't want to let me do this. 
Classes can model your original scenario quite easily (just add a `turnOn()` method to `On` and `turnOff()` to `Off`, but redux can't model my scenario (at least not without more boilerplate and lots of guards). More importantly, the available actions are localized...I don't have to create a monolithic state transition table logic...I only have to concern myself with the possible transitions for any given state. This makes it trivial to add new states or new actions, because I will never have to worry about the combinatorial explosion that can happen in a global transition table.


Let's step back. I think your approach work really well if you model state machine for internal usage.

However, Redux is meant to be for UI work, which is a side effect. You cannot control side-effect. You cannot guarantee that user will not try to turn switch off twice.

Even in idiomatic Redux, the switch case for reducer always include `default:` which mean everything else go here.

As you said, the Redux FSM models a car lock button interface which is exactly what Redux try model.


thanks for this. an interesting way, to look at things as I tend to be allergic to classes.


> I personally think your example is convoluted for such a simple example, but that's just me.

It is indeed all a matter of taste in the end, but I mean it's the exact transcription of a textbook FSM. I don't think your example would get that much simpler with a stable identifier, which brings me to:

> I don't have to create a monolithic state transition table logic

It doesn't have to be monolithic. I just created a monolithic function because it's easier for this small example. It could just as easily dispatch on state (which is what you're doing here), or on transition (which is impossible with your hierarchy), or mix and match them. I can write those examples if you're curious.

Your class example is a good example of a state machine trace (e.g. one that you might often use to create an ephemeral config object), but it's not an example of an actual persistent state machine. As soon as you use a stable identifier the type safety goes out the window.

  let stateMachine = new On();
  // Wait a bit for the user to do something
  stateMachine = statemachine.turnOff();
  // Wait again for the user to do something
  stateMachine = stateMachine.turnOn();
Depending on how you annotate the initial let, one of those two lines will cause TS to complain (or you have to do a manual cast somewhere which circumvents the type safety).

Indeed if you just care about a state machine trace the same type safety holds in the explicit state transition table case if you just use TS's literal types in the reducer's type annotations. You just explicitly call the reducers you need however many times and then persist the state machine at the very end.

That is your type safety doesn't come from the representation as an object, but rather that there is no stable state machine between invocations, but only an ephemeral trace of one whose intermediate states are immediately destroyed. Traces are valuable! But you could generate the exact same trace with an explicit state transition function and you would get the exact same type safety that way. I can write it out for you if you're curious.

> I will never have to worry about the combinatorial explosion that can happen in a global transition table.

Again you don't have to worry about a combinatorial explosion in a global transition table either if you dispatch on actions or states.

The fundamental difference between what you've outlined here and the explicit state transition table is that in your approach states are first-class and transitions are not (but rather methods attached to states), whereas the explicit state transition function treats both of them as first-class entities.

For places where you really only need an ephemeral state machine trace, rather than a state machine that persists between calls, you don't need first-class transitions because the transitions are all ephemeral and cannot be dynamically called at runtime.

Where you do have users able to dynamically call transitions at runtime, you end up needing to represent those transitions somehow, and you end with something approaching Redux (indeed I think an interesting exercise would be to implement On and Off where the user either presses "a" or "b" at the keyboard to turn on and off with your classes. I suspect you end up with just the Redux approach all over again).

EDIT: I want to emphasize I don't think Redux is free of faults. There are many things I really dislike about it and the React ecosystem it integrates into. But I don't think any of that can be chalked up to a poor representation of a state machine.


> transitions are not (but rather methods attached to states)

whose type signature has start and end state

> first-class entities

a string


> whose type signature has start and end state

As do the reducers. For example the following is a valid type signature.

  function onToOff(initialState: "on", transition: "toggle"): "off"
In each of the if clauses those are what the types are inferred as, exactly equivalent in type safety to the classes (and more flexible because you can dispatch on action).

I chose string for simplicity (string literals happen to be distinct types on their own, I could easily use anything else other than strings, e.g. interfaces). Heck it could just be integers and be even simpler.


wow a typescript lesson, because no one's ever heard of this

> Heck it could just be integers and be even simpler.

statement that has zero point, why make them?

> As do the reducers

like this? A | B | C => B | C | D

does that look like a state machine? Because state machine is this A => B & B => C & C => D


Look every of your comment is really tiring to read, so fucking long with little substance like redux code. Everyone already knows what redux is, it's really garbage and leaky. For one there is a dispatch function, where is this in the classic "pure" state machine? Why can't state transition be just a function call? Secondly there is no type that you can infer from this, you have to "write typescript" by adding type annotations like an idiot. Or else you could dispatch anything because again there need to be a dispatch function because reason.

The other commenter gave example of implementation as type safe immutable builder. You can even simplify their implementation further by using plain functions instead of classes.


let's back off a bit. I agree with the other commenter's point, which is the really important thing:

> Redux's bad ideas do not come from the fact that it models a state machine, it comes from the fact that it models it poorly

So to me it doesn't really matter whether class is the best tool to implement state machine.

If the argument is "you can do it with class/function/language feature x, however it's a lot of work to achieve composition or whatever", then the same can be said about redux: it kind of looks like a state machine, but in order to have composability/validation/static types etc, you still have to apply a bunch of "patterns". So it's just as effective (or ineffective) as the approach of rolling your own state machine.


But that's precisely where I strongly disagree. Redux's problems do not come from a poor implementation of a state machine, but rather the interactions between state machines and stateful, non-state machine representations.

Again, Redux is the purest expression of a state machine possible in a general-purpose programming language (as opposed to a specialized one like TLA+). It maps one-to-one with the usual textbook definition (technically textbooks don't have a rigorous definition for state machines, but rather finite state machines, but usually by "state machine" we just mean you take a normal FSM and just relax the finite bit by introducing some infinite component into the overall state such as an arbitrarily long list). The store is the state, the actions are transitions, and the reducer is the state transition table.

Redux's infelicities come precisely from the fact that it needs to interact with things that are not modeled as state machines! Namely, interacting with black box children and the outside world (mostly sending stuff to the outside world, Redux comes with stuff out of the box to deal with just one-way inputs from the world). And Redux doesn't come with ways out of the box to deal with those so you need to layer more stuff to make it all play nicely together. But you need at some point to interact with them to work with the JS ecosystem so you need that stuff.

If you had state machines all the way down you don't need any particular patterns other than the fundamental state machine description! Especially with Typescript's structural types, everything just works (you just pull out chunks of your store into little stores and pull chunks of your big reducer out into little reducers, it's literally just cut-and-pasting chunks of your code and giving it a new name and making new state machines all the way down).

The friction comes from interacting with React, dealing with the outside world, and figuring out various decisions of what to do about data structures that the JS stdlib doesn't decide for you out of the box (e.g. what immutable library should one use). Even the choice of mutable vs immutable is something that is decoupled from Redux proper (it turns out for incidental reasons it's easier for type systems to properly scope local effects with immutable data structures than mutable ones, but that's more an artifact of Typescript than Redux, see e.g. Rust's type system for a counterexample).

If all of that was just more state machines (and the stdlib issues were taken care of) then Redux would be absolutely lovely.

And that's not just a pie-in-the-sky hypothetical. E.g. Elm is basically what Redux would be if everything was state machines and works great in all the places Redux doesn't (Elm's infelicities in turn are of a different variety that stem from some limitations of its type system to properly express some of the structural types you'd like state machines to have, in particular a lack of structural union types that often requires duplicating the state transition table in certain ways as you break a larger state machine down into smaller state machines).


I think you’re illustrating one of redux’s real downfalls: it can be used to hold the entire state for your UI, even though it shouldn’t. All your complaints are solved when adhering to the official recommendations. Maybe you got into redux early or worked on a codebase that took things too far.

A global state object is one of the nicer features when dealing with redux.


> you're far more likely to have to change state than you'll have to change how that state is rendered. This puts redux-style solutions squarely on the wrong side of the expression problem

Could you please elaborate this?


Maybe, it's a bit hard for me to describe succinctly.

Your UI as an application likely has dozens, if not hundreds or thousands of potential states. And the more you develop the feature set of your UI, the more states you will introduce to it. The data that represents these various states is going to constantly evolve to be able to represent them: you'll have evolving business state, evolving widget states, evolving URL states, etc.

The expression problem can be summarized as a practical comparison of two types of extensibility: writing functions, which extend through composition, and writing classes, which extend through inheritance. The choice of which one is better starts with asking what is more likely to change: your data or your computation over that data.

If you have a problem where your data types are relatively static, but the computations you do on that data are constantly changing, pure functional programming is where it is at. You just write different functions to do different things, and then compose them together to do what you want. This sort of processing is perfect for a ton of usecases...things like data pipelines and etl, machine learning, web services, etc.

If you have a problem where your data types are constantly changing but your computation is relatively static, you're going to have a very bad time with a pure functional approach. You'll end up having to edit multiple functions just to change a single data type. When you decide that you no longer want to represent your state with an Array<number> and instead want to represent it with a Set<CustomObject>, you're gonna have to refactor every single function that the original version passed through. And with a massive global state object like Redux, that means not just refactoring the component that renders it, but potentially every single component above it in the HTML tree, modifying them so that they can pass it through to its final destination. That is the sort of burden that happens when you fall on the wrong side of the expression problem.

For reference:

https://wiki.c2.com/?ExpressionProblem


I didn't mean the solution had to be redux or immutable state. It could be state encapsulation like in oop, or centralizing state update (setState)


It’s a shame. Controlled side effects are a big win IMO, especially mutability.


In terms of influence on society, the New York Times is just as pernicious as any of the FAANGs.


This was true before the age of Trump and the ongoing internal war, highlighted by Bari Weiss and more, between the old guard and the new ideologues. I am most definitely not alone when I say the weight of their words have diminished greatly.


Neither did Vue, or Django, or Rails or dozens of other successful and widely adopted technologies. Svelte's issue is probably that it came out a little too late: companies have adopted React, Vue or Angular, and have sufficient inertia (existing codebases and hard-won experience) that there is little incentive to switch just for a slightly nicer syntax or state management model.


Sounds like you're describing Vue. Is their any substantial advantage over Vue that you're aware of? I think a lot of people, including myself, are just uninterested in arbitrarily and subtley different solutions to the same problem. I've used react, and it's just not as compelling as anyone made it out to be. Neither is Vue compared to React for that matter, but it appeals to me a little more.


So I'm a Vue developer who hasn't ever actually built anything in Svelte, but Svelte uses a really cool model that's completely different from Vue and React. Where Vue/React use a virtual DOM, Svelte is compiled to essentially vanilla JS. Instead of having render functions that fully replace a component, Svelte updates just the parts of the DOM that need to be updated. Because of the dramatically reduced overhead, pretty much any UI should run more efficiently under Svelte.

I'm still a big fan of the developer experience Vue provides and I'm locked into a framework for my work projects so I won't be switching those over any time soon, but I've been meaning to try out Svelte for a personal project some time.


"... instead of having render functions that fully replace a component..."

No longer the case. Vue 3 was written to have a "compiler-informed Virtual DOM"; there are a bunch of videos about it on YouTube if you're interested.


Stencil has is also a component compiler and has a very clean API (declarative through annotations like in modern angular) and standard TSX.

However the issue with both svelte and stencil is their lack of ecosystem, even if they have interop with webcomponents, today the market is too small.


> Svelte is compiled to essentially vanilla JS

How does this scale to anything remotely complex?

I've found that if you have a decent knowledge of React it's hard to make anything slow with it.


Nothing beats vanilla JS in terms of DOM manipulation speed.

https://stefankrause.net/js-frameworks-benchmark8/table.html

And Svelte is fast. It's as fast or faster than React in most synthetic benchmarks.

For how and why, see https://svelte.dev/blog/virtual-dom-is-pure-overhead (notably the intelligent compilation step which removes need for vdom)


React, Redux, Jest, and it’s ilk always came off to me as a way for Facebook to remain relevant through tech-debt and lock-in.


FWIW, Redux has _never_ been a Facebook project.

Yes, both of the creators now work on the React team (Dan Abramov and Andrew Clark), but it's always been an independent OSS project, and is currently maintained by myself and Tim Dorr.

As far as I know, FB barely even uses Redux at all internally, and that only in isolated particular teams that chose it themselves. My understanding is that they mostly use Relay for the new FB.com, and still have a lot of old-school Flux in there as well.


My bad, I didn't mean to include Redux then.

My commentary is more directed at React and Jest (as I try to steer away from that ecosystem, even though it's ideas aren't all bad):

- As GP indicates, React has had multiple API implementations to solve similar problems, feature bloat, leading to opinionated and differing best practices, mixed in with Junior devs can be a nightmare

- With Jest, I find the entire thing as a very aggressive wrapper and very tied to React itself, features like unit test `snapshots` are developer slack-off bait and have the benefit of further entrenching itself into the repository, arguably an e2e test would validate the same thing


>Yes, both of the creators now work on the React team (Dan Abramov and Andrew Clark), but it's always been an independent OSS project, and is currently maintained by myself and Tim Dorr.

The source I have says that Dan Abramov created Redux while working at Facebook on React[0]. So while Redux has never been under the official governance of FB, it was created by FB employees for a FB project (React) while in parallel working on that project.

[0] https://golden.com/wiki/Dan_Abramov_(software_engineer)-99B8...


That's wrong. Dan created Redux while he was actually unemployed. I'd have to check the exact timeline, but I believe he left Stampsy in late 2014 or early 2015, and was actually getting some funding from an OSS collective-type thing while he developed Redux in preparation for React Europe.

Redux was developed in June/July 2015, and demoed at React Europe on July 5, 2015 [0].

Redux 1.0 was released on Aug 14, 2015 [1].

Per the tweet linked from that page [2], Dan didn't join Facebook until November 2015, well after Redux had been released.

So, he most definitely was _not_ working at FB when he developed Redux.

[0] https://www.youtube.com/watch?v=xsSnOQynTHs

[1] https://github.com/reduxjs/redux/releases/tag/v1.0.0

[2] https://twitter.com/dan_abramov/status/671135846830075904


Doesn't make sense, there is nothing that benefits facebook by "dominating" a tech niche. They dont profit off of development platforms (android and .NET) like google and microsoft


See my other reply in this thread for clarity.


For me Svelte is between React and Elm. It has some of its own syntax and operator for some benefits. It is better than React in some sense (obviously not in maturity) yet it is worse than Elm (no ML features). If I need to learn some new syntax it is better worth it (no run time exceptions). I am not sure what is the long term plan for Svelte. Is there any plan to address the shortcomings of JS (for example: undefined is a not a function)?


Have you ever worked on very large React applications without Redux or Saga? I just cannot imagine any other way of keeping my application sort of understandable.


You should look at svelte stores if you haven’t already. They are amazing, and make redux seem so needlessly complex and ineloquent


> I find this in contrast to React which is often baffling and incoherent. I say this as someone that has used React professionally for 6 years. They've changed their mind at least 3 times on the API and none of it fits together today. Hooks and classes don't mix, lifecycle methods are still out there and just as confusing today as they were years ago. Mixing state and functions. It's just a horrible bag of half-baked bad ideas. And it's not even batteries included.

This, so much. It has been so frustrating to have to go from es5 classes to es6 classes + stateless functions to stateful hook oriented functions that do nothing but create just a new type of class, but also with es6 classes but with different methods. Seriously, WTF?!

I really like the ideas behind Svelte, but some things just really do not mix well with it. Like leaflet or d3. For some reason, mixing declarative rendering approaches with non-declarative approaches results in completely mind boggling buggy interactions that aren't easily understood. And typescript integration feels tacked on and doesn't play nice with some of the semantic differences between svelte and javascript, which makes me doubt how much you can really say that it is just Javascript. I mean the entire concept of a variable has completely changed to become reactive, and at that point it's not really javascript anymore, it's something that compiles to javascript while looking almost exactly like javascript. I'd love to give it a deeper look, and I probably will soon, but I'm quite skeptical of what might be hiding underneath the covers.


I'd agree on the architecture astronauts, but it would still be useful to see some good open source code bases using Svelte beyond the "todo list" level. For example:

- has a test suite

- integration with some backend framework (including secure auth)

- complex global state management requirements

- routing


But it's not JavaScript. It's something similar to JavaScript.


Is animations just as easy in svelte?


Svelte has animations and transitions already built into it, do yeah, it's real easy


I found animations a bit of a struggle, especially when combining multiple of them. There were performance bugs with some of the combined animations, and the Svelte documentation didn’t make it clear how animations could affect things like the focus on a text box.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: