Live data from Hacker News

None of my projects want to be SPAs

whatisjasongoldstein.com

331–340 of 362 posts

Re: None of my projects want to be SPAs

#331
post #317

Earlier quoted context omitted.

Browser-side routing/state management is a solved problem - SPAs can make tabs troublesome if the developer didn't put in the effort.

For God's sake, STOP trying to re-implement my browser's interface with Javascript! I don't want you to "put in the effort" to make my URL bar, back/forward buttons, and tabs work the way they naturally do in my browser; that's what my browser is FOR! Even when the developer does put in the effort, the results are usually _just_ different enough in various subtle ways from the browser's native behviour as to be annoy…

> Your forum/email interface/management API would work better as a normal website.

Good for you with your fast, always-on internet, I guess. Some consumers have to deal with expensive and unreliable 3G internet (that downgrades to 2G occasionally) - an offline-capable email (or management) SPA is indispensable for them. Sure, you could write 4 native offline apps for MacOS, Windows, iOS and Android but that is a bigger investment than targeting browser standards.

Re: None of my projects want to be SPAs

#332

Earlier quoted context omitted.

If links don't fully address an item then opening it in a tab won't work.

That isn't a limitation of SPA or browser based apps though. For that matter, even having an option to open an app multiple times is often a limitation of desktop apps. That doesn't make them somehow deficient as a platform.

It does. You don't open the "app" multiple times, you open lists or records in separate windows and/or tabs. That is a thing in desktop apps also. SPAs usually break it by tunneling everything through a single url, perhaps with anchors.

Re: None of my projects want to be SPAs

#334
post #319

Earlier quoted context omitted.

Hi, I'm a Redux maintainer. FWIW, we've got a new Redux Starter kit package that tries to be a bit more "batteries included". It includes utilities that help simplify several common use cases, including store setup, defining reducers, immutable update logic, and even creating entire "slices" of state automatically. It also includes `redux-thunk` built in, as well as some middleware that check for things like mutation…

Thanks, this is incredibly useful, I use everything in this package! It also doesn't deviate from the spirit of Redux or abstract too much, like rematch for example. Without something like this, I find that many people structure their entire Redux code based on simple tutorials. They typically only read the docs or worry about best practices and complexity after they encounter problems. This kit will have them start…

Exactly!

I understand why folks have opted to create higher-level frameworks around Redux like Rematch, and it's not "wrong" that they've done so. But, looking at Rematch code, you can't really tell that it's actually Redux underneath.

With RSK, I've aimed for an intermediate level - decreasing the amount of things you have to write by hand and the literal number of keystrokes you have to type, but preserving the idea of "dispatching actions" and using reducers.

Glad to hear that you think it looks good! If you've got any additional feedback or suggestions, please let me know.

Re: None of my projects want to be SPAs

#335
post #325

Earlier quoted context omitted.

If you don't have any routing to deal with, component state is all you need. You can still move your business logic out of the view components and use lifecycle methods and event handlers to coordinate it, but the use case you are describing is the ideal case for vanilla react.

If making global state accessible is all you need Redux for, then I don't see why that state shouldn't be: 1) persisted to a back-end and re-fetched on route 2) Persisted to localStorage If there some kind of state that doesn't neatly fit into these solutions? I know that passing around signed-in user objects is one popular use case for Redux, but in my opinion that could be easily placed into localStorage, or assign…

> persisted to a back-end and re-fetched on route

This is a huge pain in the ass and requires a ton of really tricky UX design. What happens when the data is cached and you fetch it again? Do you disable the UI and show a spinner until the request is complete (why bother caching the data in the first place)? Do you allow the user to continue making changes while the request is pending and try to reconcile conflicts when the payload is parsed (this problem is far beyond the skill level of most developers)? When the data is loaded, do you just change the content out from under the user or do you write a series of complex animated transitions to make it less jarring?

Updating state on every transition is hard, and keeping two copies of the data is also hard (cache invalidation!), which is why you shouldn't use an SPA framework unless you absolutely require it.

> If there some kind of state that doesn't neatly fit into these solutions?

The type of state is completely orthogonal to whether redux solves more problems than it creates. It should not be included by default on every project, and there are thousands of alternatives that might be a better fit. The heuristic for whether you should reach for something like redux is the size and complexity of your app, not the type of data you have. If your app consists of a single route without a lot of branches in your view tree and most of your components are only used once, you definitely don't need a state management library. Once you start adding multiple pages and lots of component reuse, something like redux starts to increase structure and maintainability at the cost of additional complexity. There is also a lot to be said for using an architecture that most of the react community is already familiar with so new developers can ramp up quickly.

> Persisted to localStorage

This is a standard practice, but you have to be careful not to spam localStorage with updates since it's significantly more expensive than in-memory object creation. I haven't profiled it but I wouldn't be surprised if it were several orders of magnitude slower. I sync the application state to localStorage in all of my apps, but I debounce it by 500ms and use equality comparison to prevent writes when no changes have been made. Obviously none of this has anything to do with redux, but redux's copy on write mechanism makes comparing states trivial, and any code that mutates the state trees requires an expensive and tricky deep comparison that negates the benefit of making the comparison in the first place (especially in the case of shouldComponentUpdate).

> assigned to a window.global_state variable

This is not the same as globally available redux state. For one, redux does all of the plumbing for subscribing to state changes and preventing unnecessary re-renders. You could spend a couple of days writing your own, buggier implementation, but why would you? Secondly, as I've argued elsewhere in the comments, the redux state tree doesn't have the aspects of global variables that make them such a dangerous anti-pattern. Writes are isolated to a single function, and all other references are read only, and it uses a synchronous message passing system with a central dispatcher that is trivial to audit. Another commenter complained about race conditions, but redux core is only designed to support synchronous operations, and there are well tested and widely used tools for managing complex, multi-step asynchronous state updates. If you have race conditions you are using the wrong tool for the job.

This is a bit off the topic of your original questions, but every time one of these redux conversations comes up there is so much vitriol from people who just absolutely hate redux for some reason, and almost every time every reason they give for why redux is a cancer is a well known anti-pattern. I guess they tried redux, hated the verbosity and saw botched implementations by other developers unfamiliar with redux, and decided that redux was the problem instead of lack of experience.

"The framework has to be idiot proof" doesn't really hold water for me, since I would love to see a react stack that scales in complexity to hundreds of components and dozens of routes that isn't horribly complex and deadly in the wrong hands. The root cause is that react is a view library, not a framework, and there is no standard architecture to provide a common language between teams and developers. Since every project is unique there is no knowledge base of best practices that aggregates over years like rails or django or laravel. A massively complex SPA _absolutely requires_ a strong, experienced lead to enforce good practices and maintainable architecture. If you have a free for all with a bunch of junior and mid-level devs you are going to get a pile of crap no matter what stack you use.

I am not a zealous redux partisan, I just prefer to work with it because I know it well and I believe it uses a pattern that scales well by keeping business logic isolated and broken up into small pieces. I'd be perfectly happy to recommend something like mobX. The only thing I'm strongly against is mixing application state with view state. Anyway, I've spent several hours and put a lot of thought into responding to questions on this thread and some of the comments have been pretty rude, frankly (not yours). I would like it if people could discuss this topic politely and constructively, and not go into it with their mind already made up and ready to do battle with anyone that disagrees with them.

Rant over :)

Re: None of my projects want to be SPAs

#336

Earlier quoted context omitted.

Does that help much? The distinction between "web app" and "web page" seems fuzzier than the question "would a SPA lib/framework be useful here?" Is Reddit a web app? Is Twitter? Facebook? They all started with server-generated HTML, all kinda feel "document-like", all of them involve scrolling (if that means anything.) Is the "app" boundary further along the chain, like at Google Docs? I think instead of trying to c…

It's really easy to throw the baby out with the bathwater in this conversation as well. A more interactive Javascript-heavy UI can improve a lot of aspects of even websites we consider to be a server-side-rendered gold standard like a forum or message board. For example, look at the right-sidebar scrubber on Flarum that lets you quickly scroll to arbitrary parts of a long forum thread: https://discuss.flarum.org/d/17…

Both of those are just fixing problems caused by the reliance on JS in the first place.

The first could be done easily with anchor links - if the content wasn't loaded dynamically.

And browsers are perfectly able to return you to the same position in the page - unless it's all loaded dynamically.

Re: None of my projects want to be SPAs

#337
post #54

Earlier quoted context omitted.

For a component here and there React is a pretty bad choice because of its size. Svelte could be a more suitable option, but I’m not so sure it passes the magpie test.

Magpie test? I couldn't find an answer on google.

The article has a reference and link to [1], where the behavior of constantly looking for new and shiny tech is likened to that of a magpie. As Svelte is still fairly new and not widely used, I think maybe it is in that class of technology.

1: https://blog.codinghorror.com/the-magpie-developer/

Re: None of my projects want to be SPAs

#339
post #335

Earlier quoted context omitted.

If making global state accessible is all you need Redux for, then I don't see why that state shouldn't be: 1) persisted to a back-end and re-fetched on route 2) Persisted to localStorage If there some kind of state that doesn't neatly fit into these solutions? I know that passing around signed-in user objects is one popular use case for Redux, but in my opinion that could be easily placed into localStorage, or assign…

> persisted to a back-end and re-fetched on route This is a huge pain in the ass and requires a ton of really tricky UX design. What happens when the data is cached and you fetch it again? Do you disable the UI and show a spinner until the request is complete (why bother caching the data in the first place)? Do you allow the user to continue making changes while the request is pending and try to reconcile conflicts w…

Thanks for the time and effort you've put into this thread, it has been very interesting reading your comments, which have a lot of content and a lot of experience behind them. I wanted to ask you about this because I've been reading about when to use Redux and when not to, and I had basically come to appreciate that it would be helpful for the kind of app that I'm working on daily. That app is very complex and very dynamic, but because it is a desktop app there isn't a lot of routing since I can fit a whole lot on one screen. When there is routing, it's usually to another view with enough complexity and code for a totally separate SPA.

So like I said, I've basically decided that Redux would be a great benefit for maintaining a consistent, easily debugged architecture for an app of this complexity, but then I came across several people talking about shared global state across routes as a good heuristic for knowing when Redux is appropriate. As mentioned, I don't really have that in my own app, so I was a bit confused by this and wanted to get some more details from you. I think you've cleared it up pretty well.

I'm completely in agreement with you about the likely source of dislike and complaining for Redux. Absolutely people jump to it too often when it isn't necessary. More generally speaking, I think there's a default attitude that front-end should be easy, and then people are rudely surprised when they find out that it's actually very hard. Distributed systems problems, cache invalidation problems, combinatorial scaling of complexity with every feature and source of user interaction... you already know this. They blame the team or the tool, but there's a fundamental complexity there that's unavoidable and deserves respect.

Anyway, thanks again, I've enjoyed reading your opinions on this.

Post reply on HN