What I wish I knew about React
bitsofco.de
bitsofco.de
The point they make, and the one everyone writing about React simply repeats, is that "it doesn't give you everything" so you can use it with any other library/framework without trouble. While this claim may be indeed correct, it doesn't mean it's a library. React is a UI framework. It's not a complete Application Framework, sure, and you may mix it with other stuff. In fact, you will generally mix it with other stuff. But I don't think that the difference library vs framework lies in providing for all of the aspects of the application or just for some parts of it.
In this particular case, the author seems to have overstepped that somewhat, saying "With a framework, you’re essentially given all the materials to build that house, and it’s up to you in what arrangement you put them in."
And in there lies the problem. That is not a framework. That's Home Depot. A framework does indeed tell you in what arrangement you're supposed to put the materials. It's in fact this that makes it a framework. It gives you structure. Or at least, the basis for the structure. You put your materials into the arrangement the framework suggests.
React is only concerned with UI, sure. But then again it does give you quite a bit of structure. It does tell you how you're supposed to arrange and build your UI. You extend this class with these methods, or you create this kind of function using these functions in this way. You put your rendering here, and return it in this way... and then the framework will run it.
What is correct is that React is for UI. So, sure, it will not tell you how you should do your API calls. But not because it's not a framework, but because API calls are not a UI concern.
So with that in mind, you can use React as both. If you ever call `ReactDOM.render()` just once and then live in React land, with all the lifecycle hooks and whatnot, you're essentially treating React as a framework, as React calls everything after the first initialize.
If you call `ReactDOM.render` in multiple places or have something around that handles that for you, then you're using React as a library.
And I think most people do use React as a framework. (But I could be underestimating those who use it in the second way, of course).
We needed to do it incrementally from a server side rendered Java application, with jQuery and a lot of custom spaghetti code.
At first we migrated the server side templates to JSX and started to use React as a library by calling ReactDOM.renderToString. The first thing our JavaScript did was render the React templates similar to using Handlebars. Then the rest of our code kicked in using jQuery bindings and it’s events logic.
Now that our templates were all JSX. It was simple that start converting leaf “components” with simple state into ReactDOM.render instead. Often needing ReactDOM.unmountComponent to “refresh” the state And rerender everything like the jQuery based code needed.
Finally, we worked our way up the stack of components so that more and more were “just normal react components without calls to ReactDOM.
The last thing we did was migrate the top level to use ReactDOM.render and we were fully React based.
FWIW, we thought about Redux but didn’t use it. We used the patterns from Redux, but felt we didn’t need a library to manage our data. This was also pre-Hooks.
All in all took 1 dev on a team of 9, that all kept working on the codebase, about 4 months working on it off and on 50% time focused on the migration.
There were no issues caused along the way, the automated tests didn’t need to be changed (except for the new features - which were orthogonal to the React migration), and customers had a (unnoticeable) latency improvement comparing the metrics at the start and end of the migration.
The incremental use was a huge reason we picked React. Not only to migrate to React but also because we can do the inverse process when we want to migrate away.
P.S. We finished this migration Jan 2019. Since then the productivity of the team has noticeably increased. Even new hire “ramp up” has been reduced with them producing production code faster, on average, than pre-React. I’m sure these successes would be true for a migration to any modern UI tool e.g. Angular or Vue.
I've heard this referred as the 'Hollywood principle', as in 'Don't call us, we'll call you'.
Nobody uses React that way. Besides, React is still very much the one calling you when you're dealing w/ lifecycle methods, useEffect/useCallback, suspense, etc.
Hi. I make complicated web UIs. I call React that way sometimes, because sometimes you don't want your entire UI to be one big React component.
This is in contrast to frameworks like Angular which try to reinvent to entire ecosystem in an "Angular style". Which is a massive pain if the Angular version has a bug, doesn't implement the feature you need, or is simply far too complicated because it's trying to be everything to everyone. In React, there are usually 2 or 3 options for everything with different trade-offs. And this is amazing, because you can pick the library that works for your project.
At the end of the day, what difference does it make? React may not be as opinionated as other application frameworks, but it's also non completely un-opionionated.
If you write a full ui in React, whats the level of effort involved to port it back to vanilla js, or even another framework? It's certainly not trivial. IMO that's the only qualifier needed.
But I agree, it's all about marketing.
I do think the "win" that React has here is that it's easy to introduce React into an existing project with minimal overhead. In that sense I think its closer to library than framework, but after enough time you will inevitably end up with a "React app" and not a "web app with some React".
And it's also constantly evolving and getting better. Just recently I started a React project with class components only to learn that hooks are now a thing and they remove a lot of boilerplate code. Even with redux, redux supports hooks as well so you can scrap that entire connect() stuff alltogether. Just back to simple function components.
I don’t think it’s really too big of a deal, but I wish people would be more realistic and use less hyperbole. Everything has trade-offs, one’s own personal honey moon ending does not mean we were all blind and/or ignoring the faults with things.
When the latter become dominant, there should be even more subsequent, innovative ones.
And the cycle will repeat.
But it's less net shittiness with every generation. And how many generations are we even in so far? C is '70s security gore, C++ is an '80s attempt to force OO memes that we've come to regret onto the '70s security gore, Python and Java are '90s OO memes in earnest, JavaScript and PHP were kludgy mistakes slapped together in a fit of desperate confusion to get some web shit to run, aaand...
Not necessarily because I have many complaints about it, but because I consider it in essence very similar to C++17, with (not-too-)different syntax and a few different but important design decisions in the core language and standard library. Seeing it sold as a radical paradigm shift from C++ has always left me feeling that some people are in for disappointment down the line.
As I continue to see how very experienced C++ programmers make exploitable bugs that passes all reviews and that are compilation errors in Rust saying that Rust is C++ with a different syntax is very naive.
HN is rarely the place to read constructive comments about JavaScript and frontend development.
Personally I've been developing web apps for 10 years (with technologies such as Spring, ASP.NET, CakePHP, Symfony, Django, jQuery, Backbone.js, Angular 1) and I quite enjoy React. I think it makes my job easier and I feel productive with it.
Also, TypeScript is awesome.
I consider this a slight inconvenience but still a better system than having the dang hammer around to pound spammers ..
/r/webdev, /r/javascript and /r/reactjs too
While I'm not particularly hostile to javascript or React myself, I do notice that over time, I tend to avoid it whenever I can. It wasn't too long ago that I made (gentle) fun of Intercooler.js (what happened to that person and their tireless efforts to insert it into any vaguely relevant conversation?), for example.
But nowadays, I'm fully on the Phoenix LiveView bandwagon (React/js on the server!), and I would absolutely use Svelte or Intercooler if LiveView wasn't an option, I grumble whenever I need to deal with my js pipeline (Webpack, PostCSS, etc.), and whenever I do need to deal with it, I get an almost existential 'where did things go wrong' feeling. Maybe I'm just getting old, in front-end developer terms anyways.
All I know is that for the past year I've barely kept up to date on the latest in React (Hooks?!), CSS (grids? flexbox?), js bundlers, browser features (webworkers? the latest in LocalStorage? webcomponents?), and so on, and instead I've been dealing with databases, servers (nginx, linux, etc.), and other 'back-end' things instead.
I feel much, much less frustration because suddenly things stop working and I need to dive into the complex world of webpack and its loaders, CSS and it's various browser incompatibilities, and so on. But I also feel that the things I /do/ learn will probably be valuable for years to come.
The insane amount of stuff I've learned about jQuery is practically worthless now. The same goes for Bootstrap and Backbone.js. Or various CSS layout tricks (dear god the floats). But what I'm learning about Postgres and Ngix and Railsy back-ends seems like the kind of stuff I'll be able to use (and make a living off) for a long time to come.
I do really like TypeScript though. I'd love to use that more :).
And you could transition off of Typescript just as gradually as you could transition on to it.
JS isn't going to get compile time anything. There was an attempt at adding "strong mode" by one of the google / chrome teams iirc and that went nowhere.
I think there were discussions of doing that at some point, but it seems to have gone nowhere.
You have to be aware these features would need to be manually converted back to JS were you ever to switch back. Honestly this would likely not be a significant amount of work, especially if you don't overuse them, but just to make you (GP) aware.
On the other hand Flow is much less cool than TypeScript these days. Plus using it for development under Windows have issues, although FB has started paying attention to them.
Although I still hit enough annoyances that I'd go straight to `.ts` files for my next project.
So, so true. Not even just JS though. Community can be rough on people generally.
Give it a little time, see a few codebases, extend and build a few apps, then come back. Now people have some credible stuff to say. We can’t comment much about how great Hooks are after reading a few Medium posts. I’ll see in a few months when it’s all over the codebase.
HN will be full of ‘we rebuilt our api in GraphQl and boy things are a mess’ in 2 years.
For example, Apollo will cache api requests, but what about local application state? Their local caching library is cumbersome to use. If you wanted to update local state, you either need to write a mutation, or manually fetch data from the cache and change it. For the former, I find writing GraphQL mutations more verbose and cumbersome than Redux.
In the latter, you need to worry about fetching, changing and saving state every time you need to make a change. With Redux on the other hand, your current state is fetched and saved for you automatically and you just need to worry about describing the state change in the reducer.
I also dislike the Query and Mutation components. The Query component can be fine for simple use cases, but it still ties your API calls directly to your component. What this often means that any business logic associated with the request goes in the component as well, leading your components to become bloated and untested.
The mutation component is even worse leading to super hard to understand code - you are basically writing your API request layer using HTML markup. For me its so much simpler to just have functions that call APIs directly instead of trying to understand some strange markup hierarchy.
In short, I can see the appeal of Apollo if your app had very little frontend state and just needed to be a reflection of the server. However, as your codebase grows in complexity, the patterns that Apollo encourages you to use lead to bloated and unmaintainable code.
Apollo is for GraphQL. I'm not sure why you'd try to use it's internal caching system to add local application stuff. Note that using Apollo does not stop you from continuing to use Redux.
> The Query component can be fine for simple use cases, but it still ties your API calls directly to your component.
This is what hooks aim to solve.
The Apollo caching system hasn’t been all roses; it can be pretty easy to wipe out parts of a cached entity you were needing on a view with the response to a mutation on a different view if you’re inconsistent with query and mutation response structure. But I find it convenient after getting the hang of its pitfalls.
Nothing surprising. Infact, I don't understand why the article is so highly upvoted.
Any jokes, memes or puns are frowned upon the community 99% of the time. I suppose it's considered redundant or not-constructive...
HN has a great sense of humor. I know this of course because my jokes have been upvoted.
There are lot of very smart people there. You compare the recommendations in music/books/cinema between them and reddit and it is "People" vs "Cahiers du Cinema".They tend to create lots of Internet culture, the humor is caustic but it can touch genius from time to time and they are very open regarding topics like sexuality,depression, economics and so on.It is proof there is always more that meet the eye.
My point is there are affectations in both communities (4chan and HN) that are strange opposites of one another. Here, people often pretend to be more polite and erudite than they are, there, people often act more rudely than they normally would, because that's the culture, that's the mask you're expected to wear.
And on both sides there's a pretension which you're kind of displaying. You're talking about a site as vast and varied as Reddit as a whole as if it were a single forum, and dismissing it as qualitatively lesser than an anonymous imageboard that has shitposting as a central part of its identity. Find some well moderated subreddits for any particular genre and you'll find quality of conversation equal to anything on 4chan, or even HN.
Also, you know, 4chan has been around long enough at this point that a lot of "out of touch academics" and "journalist boomers" have probably been there.
But the pretentiousness annoys me sometimes, at the end of the day it's another forum of people who don't think they're part of a hive-mind... which we definitely are
HN readership is as establishment and conventional as it goes, it is the "study hard for the SAT/GRE/GMAT" crowd.
- if you learned react by yourself years ago, you had to go through a lot of pain: the doc was terrible, the ecosystem a moving flaky target and conventions were not established. Things are better today, but it's not something you forget. Somebody starting react in 2018, and with create-react-app, will feel much happier.
- if you come from projects were you sparkled JS a bit, and suddenly you move to SPA with react, which is the experience of many, it feels like a wall. In fact, for many, React is the gateway to JS, and it pays the price for it: if you dislike working with JS (which is not uncommon if you come from another language like Ruby, Python, etc), you associate it with React. If you don't do JS full time and suddently must embrace the full stack of it just to make a UI, it's overwhelming. And despite the message you can use bare bone react, nobody does that: you use react, you eat the burger tower with it. Webpack reputation espacially, tainted react reputation.
- react has been oversold and overhyped. It doesn't help that the react community has been in deny of all its problems for years. They fixed many eventually, but before they did, they claimed it was all wonderful. It felt insulting for some people, espacially senior devs from other techs who knew the youngsters in front of them were full of it.
- the whole store concept has been a debacle. First there was a mysterious name (it's a plane, it's a train, it's flux!), but no solution. Then there were too many. Then Redux won. But Redux is so full of boilerplate. But wait, "you don't need Redux". But then people hacked many solutions internally to avoid redux with no guidance. Then redux toolkit and react provider arrived. In general, react and its ecosystem changed too fast. Way too fast. Unless it's your full time job, it's very hard to keep up. If all techs did that, we'll never be working. Combine that with the JS community desire to always use the latest toy, and you get a rat race. People have work to do, they don't want to deal with drama. React ecosystem is a drama queen.
- there is no convention on how to write a react project. Everytime you move to a project, it's a new project. You relearn the layout, the naming convention, the way store is handled, how things are passed around, the libs used for basic things, the testing infra, glue code for said libs, how you deal with css, the granularity of components, API best practices, etc. Not to mention the flavor you are in, depending of the version of react used and the fashion at the time. That's just for react. Then you deal with the other JS techs.
- so now, how do you know what to do? Who to trust? Where to get the gospel from? Thousand of tutorials, many imcomplete, obsolete, unpractical, specialized or dishonest. Just the way to manipulate something as simple as props have so many variants with different implications, and you got them all online. All. Of. Them. If you come from the ordered and well established world of backend frameworks, it's a mad house.
- then there are the gotachas. setState() is asynchronous, auto bind on createClass, but not on extends (but yes if render()). There you gotta call super(props), not here, useEffect dependancy management... React is full of them.
- when the magic doesn't get you, it lets you down. Some basic operations, like settings classes, preventDefault, communicating with the parent, etc. that you do all the time, are incredibly verbose for no good reason ("it's just JS you all!). Most other libs have shortcuts for them. In fact, most react projects add libs to get on par. When I train people in react and they ask me how to do this simple thing, I get desperate looks: "really?".
- integrating react with legacy frameworks like RoR, Symphony or Django is really, really not fun if you don't have a SPA with an REST API. And everybody does it differently.
- react native code reuse was a lie. A damn lie. And its great perfs as well. Nobody likes to be lied to.
- the immutability story is the last straw. I get the benefit of it. But for the vast majority of projects I met in the wild, the cost is way to high. This has so many ramifications I would need another comment just for this one.
Bottom line, if you work with seasonned programmers like it's often heard on HN, you can make the best of react. If you don't, and I work a lot with schools, administrations, average corporate IT deps, etc., the cost of react is going to weight on the team.
The teams that can manage React correctly are not that many outside of our bubble.
And for the ones that can, the price of using react may just be not worth it.
When I give the same exercice to do with Vue and React, beginners doing Vue finish in half the time. So I usually advice for Vue. Life is short, and you are probably not facebook at scale.
React native performance is good too it just doesn't come for free. You need to know how to do native animations and you need to do late binding and all the other performance optimisations you should be doing with React anyway.
The only thing that lets React Native down is the tooling. I've had the debugger repeatedly push stale code on refreshes, the source mapping is atrocious and sometimes the network debugger just refuses to work. Also sometimes the app fails to load and you need to reload the app and or restart the debugger and or restart the packager in the right order.
I've found RN performance passable but underwhelming. It seems generally worse than a good native UI, and no better than a mobile web UI.
I don't understand why the JS is run in a separate thread, rather than just using the UI thread for UI (as it's intended for). By making all the interaction with the native toolkit asynchronous, it adds extra latency and leads to unavoidable glitches in native widgets used as controlled components.
Animation in React Native is much more of a hassle than UIKit or even CSS. (About the same as native Android, though, where it's also pretty tedious.)
My experience was that RN was way more helpful on Android than on iOS, in general. But that has more to do with Android than RN, which achieves its utility on that platform by papering over a pile of bad decisions, inexplicable awkwardness, and half-finished-apparently-by-the-Summer-interns APIs, none of which should be problems in the first place. I'd seriously consider using it for just for Android even if I wrote a separate, native iOS version of the same app.
The tools are starting to get fairly good on Android. There’s a lot to like about Android Studio. But the actual platform APIs are still a mess.
The extra latency for a layout change is most noticeable if it's an animation hence why you should use native animations not JS polling animations. I agree the Animations API is not as easy as CSS. If you want to do complicated stuff you need a lot of experience with it. This is one of the major hurdles for new RN devs.
Its possible to get good performance our of it, better than mobile web UI, you just need to have some experience with what costs and what doesn't.
I’m working on an alternative to React Native that does exactly this, and it works absolutely fine: React NativeScript.
In NativeScript (and thus also React NativeScript), the JS logic and the UI both execute on the UI thread. Furthermore, you can synchronously access any native API without needing to set up bridging code; bindings to the whole Obj-C/Java runtimes are ready-generated.
If I'm coding in a style that works fine on web, and also works fine in native code, but is slow in React Native, then I'd suggest I'm not the one doing it wrong, it's React Native itself.
This way layout changes are smaller packets so it doesn't saturate the low bandwidth of the thread bridge.
Even if they were to stick with the multithreaded architecture, it should be possible to build a layout structure in the background thread and just hand ownership over to the UI thread. I believe the RN team are working on doing this with their new Hermes runtime (sharing objects directly rather than marshalling them into and out of the JS engine), so that ought to help a bit. But I really think the threading model is just wrong-headed in the first place.
Its possible to get good performance our of it, better than mobile web UI
Is there a case study or even just an example that demonstrates that? I'm skeptical. Mobile browsers are very fast these days, so there's no obvious reason why RN should necessarily be faster.
I suppose RN might have an edge if you're making extensive use of native code. But then calling native code from RN is very laborious, so RN doesn't exactly pull its own weight in that scenario.
I think the reason RN is faster is because mobile browsers have to support decades of crufty CSS in their layout engines while native layout engines are much more lean and ripe for optimisation. React Native uses Yoga layout engine so there may actually be benchmarks available on that.
Totally agreed. I’m working on an alternative to React Native that addresses exactly this: React NativeScript.
In NativeScript (and thus also React NativeScript), the JS logic and the UI both execute on the UI thread. Furthermore, you can synchronously access any native API without needing to set up bridging code; bindings to the whole Obj-C/Java runtimes are ready-generated to begin with.
Stuff like this is rarely part of the sales pitch for any framework. You only find out after being locked in neck deep. Still from all the browser gui frameworks I think react is the safest choice.
Why? Well it is reliable and scalable enough and create-react-app makes the whole experience acceptable. It will not get you into trouble. Choosing any of its non-mainstream competitors might get you into deep shit if the project fails. Choosing any of its mainstream competitors like Vue or Angular seems like not a big improvement over react (if it even is) and will make you go into defensive mode anytime a junior dev knows that feature x would have been easier to implement in react.
- It starts you off with about 40kB of minified gzipped javascript; some developers feel that it's too much.
- It is not and probably never will be the most performant framework out there, which upsets quite a few people (although the work that the React core team is doing with Concurrent Mode probably means that from the end user's perspective React will feel fast enough).
- It has become the default way for many frontend developers to write JavaScript; I know I am personally guilty of that. This generates a lot of resentment from more experienced developers who have learned to prioritise minimalistic JavaScript bundles over developer experience.
I've seen it in a couple of other individuals as well, and I feel it's becoming more widespread, though I hope I'm wrong. In these instances, I see the framework existing both in the code as well as the mind, and operating outside of it is often a leap too far.
this has been my experience too, I'm a full stack engineer playing a devops role right now on a greenfield govt project. Getting our CI/CD pipeline going within our environment constraints with react has been a pain in the ass. Every time something goes wrong the front end dev just kinda throws his hands up and basically tells me its my problem. I ended up having to go through all the issues opened on github to find solutions and implement them myself. I'm no javascript expert but to me the solutions seem to be super hacky when I've found other frameworks out there that handle these things out the box or more gracefully.
I was on a project supporting legacy code for a long time before this, and was quite looking forward to working with newer js frameworks but this left a sour taste in my mouth. And I already had a bad impression of react prior. I might look into pushing for some of the alternate frameworks out there.
> the solutions seem to be super hacky when I've found other frameworks out there that handle these things out the box or more gracefully.
I'm curious to hear what alternative frameworks handled these things better? The only one I've used recently, other than React, is Vue.
There's a slew of workarounds offered in that github issue, most people (including another team in my org) opted to just rebuild the app every time a docker container is created which kind of defeats one of the major pros of using docker IMO.
I ultimately ended up forking off this repository and customizing it to my needs https://github.com/beam-australia/react-env
that solution in itself is very hacky.
as far as I know, vue doesn't have this feature either but I think next.js and nuxt.js does.
I probably don't appreciate the complexity of the issue, but I would say environment variables are not React's concern; it’s up to you how to architect your code. If you want runtime environment variables, then either add them to the html that React will render into, so that the javascript code can read these variables in before rendering, or have an api endpoint that your app will query before or during rendering and will get all the relevant config information from it.
> but I think next.js and nuxt.js does
Probably because they server-side-render. And even if your app renders on the client side; even if you don't use next, nuxt or whatever, there is no-one stopping you from dynamically serving the html skeleton with the relevant variables in it.
But then, it all probably has been mentioned in that issue. I wonder why it wouldn't be a good solution.
I don't consider it part of the "code" but part of configuring the application based on the environment you're deploying it on(Precisely why the FE dev basically said its not his problem). The fact that a lot of people are suggesting you just build the app every time you deploy a docker container is really concerning to me.
> I wonder why it wouldn't be a good solution.
it just feels dirty. it's the fact that I have to add these into the code that it feels like a hacky solution for a production app. using a shell script to read read the OS environment variables to create an ENV file then convert that ENV file to a javascript file that is then read, it seems like many things can potentially go wrong.
Ideally they would just deal with this within the dotnev library
Here, for example, is an article describing such an injection at the nginx level: https://medium.com/@jans.tuomi/how-to-use-environment-variab.... Or you can serve index.html using a full-fledged dynamic server, such as Node, and inject environment variables there (and probably cache the response for good measure as well, not to overstrain Node). This really is not something that is React’s responsibility — although it may very well be the responsibility of the frontend developer to set this all up.
All those solutions you mentioned I've considered and are mentioned in the github issue. I just think its way too much work and overly complicated for what is basically a prototype. Which is why I opted for the simple hacky solution.
> This really is not something that is React’s responsibility
This is why I'm already pushing for our team to move off react I don't think its the right fit for us. We also don't like JSX
I don't use React day to day in a big team so I can't comment on the maintainability gains, but as a user all I see is websites degrading the experience when migrating to SPA. If state of the art front end engineering with React is Facebook or Reddit then it's hugely disappointing.
To me that "entire stuff" is about the only thing that is good about redux (barely does dependency injection). See people need to understand that hook is a good API from the library authoring point of view (the react team's and react component library authors') it's not such a clean abstraction for people to write application on top of while unneccesarily make their code depend on magic react functions all over the place.
I cant count how many "data fetching hook solutions" I've seen on twitter. If something does data fetching, then it needs to know about fetch() and may be a reactivity abstraction like promise or rx. A hook is completely unjustified.
Hooks definitely lead you towards a different approach for writing components with a different set of tradeoffs. I talked about this in my post "Thoughts on React Hooks, Redux, and Separation of Concerns" [0], and my ReactBoston 2019 talk on "Hooks, HOCs, and Tradeoffs".
For React-Redux specifically, `connect` still works fine and we will be supporting it indefinitely. However, we're now recommending that people use our hooks API as the default approach, because it's typically simpler to work with and there's less indirection.
[0] https://blog.isquaredsoftware.com/2019/07/blogged-answers-th...
[1] https://blog.isquaredsoftware.com/2019/09/presentation-hooks...
The best explanation oh how useEffect works is by Dan Abramov [1] It is also worth reading his article on React as a UI Runtime as it is a good explanation of React conceptually under the hood.
[0] https://courses.reacttraining.com/courses/250055/lectures/38... (Can sign in for free to watch this one video.)
If you're not doing declarative programming with React then you're swimming upstream.
Problem is that the concept of declarative programming would be very difficult to get beginners to grasp. Once you grasp it though, it's absolutely incredibly powerful and importantly - simple.
And this is where React loses beginners who jump to more intuitive programming models.
You can design all the declarative things you want, but someone will eventually come up with a requirement that doesn't appear to fit a declarative structure, such as an event that fires 2 seconds after something else happens.
And so to resolve that you can construct state machines with transition states to get back to a declarative model, but those state machines can quickly become a bigger headache to maintain (yes, even with redux) than if you'd just been able to setTimeout from the component in the first place.
And you start with the best of intentions of re-usable components but find more things that ought to be owned by the component pushed up to the store and suddenly there isn't a neatly re-usable component but an empty shell of something that still needs the other half plumbed in manually every time.
I love the idea that you can abstract everything happening in an application to state and render reproducibly from that, but the reality is that it's really hard and time-expensive to do compared to jquery.
But that would be fine if the tooling was there. If React had a CLI like the AngularCLI it wouldn't be such a problem to add new actions, or new pieces of state, or new components.
But it doesn't, so each new component ends up adding a little more state into the state machine which ends up breaking types in far off places.
Now there's probably an assumption about how state is built up or how reducers are typed or how actions are defined that I'm missing some reason why this shouldn't be happening. But it is happening, it's the reality for the project I've been working on and it's a real headache.
I honestly don’t see the issue with your example.
I’d use an event handler to work out when something happened. This would set the timeout, and the handle would be stored as a ref. I’d have a use effect hook to clean up the timer, so when the component is unmounted the timeout is cleared.
What’s the issue here?
You can't drop a bit of it into your project. It distorts how you build the webapp.
jQueryUI is a library. You can add it in and your code is still vaguely the same.
React is a framework pretending to be a library so people can't say "Oh, what? another framework?"
As soon as you use React, you're in the react universe, not the normal webdev universe.
With a normal webapp, I can just import an external js library. With react, I must look for projects that translate those library into the react universe (react-bootstrap etc).
(I don’t disagree with anything else you said)
Fair enough if you love react then this is acceptable. But it pushes the definition of a library, when just using react means that other libraries need to conform to react to properly work with it.
React does some things nicely. But it's not "It's just a library. Drop it into your existing project. And you're done."
The constructor is the wrong place for data fetching in React class components as far as I remember anyway. I don't remember the exact reason, but it always has been somewhat non-obvious and you always needed to understand the React lifecycle to avoid bugs in that kind of code.
Not really because there's nothing object oriented about React.Component. It's just a wrapper for a function implemented as a class.
It is much easier to accidentally create infinite loops with useEffect that you would never create with class components, and some of the code you write turns out to be more verbose and less expressive, such as when trying to diff previous and current values of state & needing to create extra state variables with useState for each such value you need to react on.
Hooks seem very appealing at first (I lean more FP than OOP in general), but the bugs and slipshod initial rollout out of beta really does not inspire much confidence. Even today I still encounter weird issues.
Classes in React generate false expectations.
In ASP you wouldn't put initialisation code in the page constructor either, it would go in Page_Init, Page_Load, etc.
Of course the tooling there made it both easier to put in the right place and harder to edit the page constructor to stick it in the wrong place.
I agree that for the easiest of use cases, lifecycle methods make sense. But you very quickly leave that comfortable zone and then it just becomes painful and confusing.
Less so than I've been tripped up by react hooks certainly so it's been a surprise that many here are describing them as being much easier and simpler than classes.
Classes had limits and some pitfalls but it's been frustrating that lifecycle methods have been retired and deprecated because sometimes they felt like the natural place to do something.
onCreate/onStart/onResume and onComponentDidMount, onPause/onStop/onDestroy and onComponentWillUnmount are basically the same. Be it Android, Swing, or Qt, everywhere it's the same pattern.
React is the first framework which actually feels like UI development on the web, not anymore like JS spaghetti.
In fact, having internal state, externally given props, exposing events, and being declared through markup is exactly the same between React, Android or Qt.
The only thing React brought to the table was allowing you to basically just recreate the children every time something changed, and it'd diff automatically.
For us native devs this thread is hilarious, because it's just JS decs complaining over things we've always done
> JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
You've been tricked into thinking you're using a class, but you're really not. I understand it's a useful trick, but hooks are more idiomatic for JS as a language.
As a side note, one of the problems with JS is that the community often disagrees about what JS is: https://babeljs.io/blog/2018/07/27/removing-babels-stage-pre...
It may be technically correct, but C++ and now JS have a "class" keyword for a reason, and that's to steer you towards organising your code into classes which operate in certain ways. In both languages you can avoid using classes, sure, or abuse classes in various ways. But fundamentally they do have classes.
I guess, yes, there's different semantics between the constructor and componentDidMount, but it's UI library, this is common that "when a constructor is call there is no guarantee the component has actually mounted".
You can't `new MyRecyclerView(...)`, you've got to `LayoutInflater.inflate(MyRecyclerView, parent)`, which isn't any different from `React.render(MyApp, parent)`.
Was the issue with `this` in componentWillRecieveProps not solved by using an arrow function? If so, that just sounds like normal JS binding woes.
Facebook recommend composition over inheritance, but you can totally extend React.Component and even get abstract classes involved. In my custom React renderer, all the components in the library are based off React.Component class inheritance.
But that’s the point. The way in which classes operate in JS is different from the way classes operate in OOP focused languages like C++, Java and C#. That’s because the language doesn’t have classes, but rather syntax to make it look like it does. On the surface your code will be organized in similar ways but the underlying behavior is different.
At least it looks like we agree that React is a decent framework :-)
That said, for us devs who do both native and JS code, the condescending part is quite hilarious as well ;-)
It's just funny when pure JS devs go all "no you won't convince me to compile my code / use classes with lifecycles / etc, that's against the natural order!!!"
Say you have a component that renders some data it fetches from the backend, and it received the ID via a prop. In a class based component you might be inclined to write the fetching logic in the componentDidMount or maybe the constructor. However, if you change the ID you feed the component, the component will update instead of being recreated. In the naive class based version it won't refetch the data, and won't behave correctly. With useEffect hooks you don't really care anymore, you can reason about side effects in the same declarative way. You express the fact that fetching new data is a dependency of the prop changing, which holds true both on first render and later on update.
The hooks API fixed a handful of these 'mistakes' that were still present in the class based API. I agree that the syntax might look awkward at first, but the hooks API is much better thought out than the class based one.
(Some anecdata: almost any component that I rewrote in hooks-style has been halved in number of lines of code, the concepts have been much less spread out over the file. See this tweet for an example: https://twitter.com/threepointone/status/1056594421079261185)
We can replace mentally any <div> or <span> on the page with <iframe src="someScriptFunction()"/>. When the application state (fuzzy term but still) changes we request these content generating functions to re-execute.
The VDOM is just an implementation detail - agreement on what these someScriptFunction()'s shall return. Conceptually they may return just html and so we can use:
function onDataModelChange(model) {
element.html = provideHtmlRenderingOf(model);
}
can be used instead of reconciliation (diffing). Performance of such updates will be the same, if not better than React's, BTW.The only problem of element.html = ... approach is that such updates will loose runtime state. For example, if you have <textarea> replaced that way you will loose its current editing state - undo/redo stack, caret positioning, etc.
So VDOM and reconciliation mechanism is a palliative - to do not loose runtime states on updates. But, again, it is not a panacea. Think about <div contenteditable/> based editors, their content cannot be reactive in principle.
That update-only-what-is-needed reasoning frequently used by React people to promote "speed" hypothesis is a bit misleading - it was introduced for different reasons really.
Elegant, simple concepts of React - they are outweighed by the environment they live in. React allows for rapid prototyping, provokes ideas which sometimes break traditional ways. Anyways, I will leave these thoughts with saying that personally I don't have issues with it. I adapt React to what I want - it doesn't adapt my thinking ;)
Even if I'd write the backend as an API without no SSR, I would prefer to write the frontend in HTML + CSS + vanilla JS + jQuery. It feels more intuitive to me as there are no abstractions to complicate things, no opinionated framework to force me do things its predefined way.
Using a framework means your project will never purely be yours.
React license:
> The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates, (ii) against any party if such Patent Assertion arises in whole or in part from any software, technology, product or service of Facebook or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software.
https://engineering.fb.com/web/relicensing-react-jest-flow-a...
https://github.com/facebook/react/commit/b765fb25ebc6e53bb8d...
I personally am not impressed with React and don’t get what all the fuss is about. We’ve had Angular, jQuery and a whole bunch of stuff over the years and each one managed to become a ‘a thing’ for a while
I come from a game development background, and there we had Immediate GUI's for some time now (https://eliasdaler.wordpress.com/2016/05/31/imgui-sfml-tutor...). React basically translates this concept to the web, and does some optimizations to not rebuild the entire DOM from scratch, and only rebuild when state changes and not every frame.
Writing a 'render function' is simpler and easier than building a structure of widgets and letting them handle events. (I like simple and easy)
Anyway, it seems both react and flutter are also gaining on the mobile apps developments, and web developers are very happy using React.
Of course frameworks come and go, but React introduced a shift of mind when programming GUI's.
What will happen to this way when React is "outroduced" ?
Don’t get me wrong it has a lot to like about it - but the only revolution is that Facebook’s might propelled this in the minds of developers all over.
Every time I see someone claim such a thing, it's usually only distantly related. Like it too has a render() function.
I mean, you can find old FRP phd/whitepapers but I don't think they prohibit you from ever saying "$X introduced $concept" without a disclaimer that it wasn't the first. So if you're going to insist, then why not share some prior art for the discussion?
Since those things really miss the 'react' part of React, it is still quite different.
I used to work for a portal vendor called Plumtree in 2004 (later acquired by BEA and then Oracle) and much of their stuff did client-side rendering.
The idea of making web interfaces more declarative and less tied to DOM manipulation has been evolving since then. Many developers I'd encounter back in those days moaned that we were not using jQuery or MooTools or whatever.
React is very nice - don't get me wrong - but its popularity has much to do with the mindset of developers shifting away from seeing JavaScript as a way of 'adding spruce' to 'web pages'.
A quick look at SmartClient shows that it still uses the old OO way of widget composition (widgets having .show() and .hide() methods, etc). This is not at all how React works. In react you render your GUI based on state, and events never manipulate widgets, they manipulate state. It's a functional way of approaching GUI's instead of an Object Oriented way.
The React way of building GUI's is now used outside of the web, for mobile apps through React Native and Flutter. This is completely different that any pre-existing GUI frameworks.
You declare how your view looks like, wire up the state and user interaction stuff and you have a self contained puece of code.
People doing UI stuff, before the advent of React usually highly appreciate it because they know how much work it takes to actually build a usable UI in vanilla JS.
"Everything an HTML tag" is an insane mantra to have. As author points out, what in the world does a <Query> tag even do? It might make sense to us because we're used to it now, but the semantics of a tag is completely lost in this "new way" of using them (don't call it declarative because that's not what it technically is; it's markup). These days I'm creating HOCs on top of HOCs to support different behavior (from redux stores, to authentication HOCs, to "don't render this thing on the server" async components). It's, simply put, a terrible idea. And everyone just bought into it because the guys at Facebook must be really smart.
The lifecycle hooks are just confusing and unnecessary. They are side-effects of over-engineering. And to add insult to injury, they change every few versions (so old code will inevitably break on new React versions).
SSR. I've brought this point up on HN before, but doing server-side rendering in React is absolutely ridiculous. Every time I need to implement it, I'm constantly battling async stuff, state management, webpack/babel, hot module reloading issues, shimming `window` or `document` on the server side, etc. Boy do I miss the days when I was building stuff in PHP and HTML was simply rendered when I ran the damn thing.
It's crazy to me that it's normal now to have like 3-4 compilation/transpilation steps when working on a simple JS-based app.
There are actually very few websites that 'require' an app-in-browser experience. And for many of those, clever usage of jQuery plugins works well enough.
One of the reasons the virtual DOM exists is because it really tries to get around the browser limitations on DOM rendering. We were also all trying to manage templates and data binding. If you remove these three things, most of us could architect very simple JS apps with a singleton object.
It’s as soon as you need to define the dynamic template structure, bind data to it, and do everything in a browser performant way, is when we started trading away the simplicity for off the shelf complexity that solves mostly these three problems.
It might have been simpler (what ever that means) but the result was a nightmare to maintain and add to.
It’s almost like just when we’re ready to write some dope Jquery code, it’s time to go write in a new framework.
I can say for certain the best React code we will all write will be 5 years from now, but, it’ll be time to move on to the next one.
Many large websites still use server side rendering (in whatever language they want), and js to refresh data client-side as required and respond to user actions, pulling data from the server side. There is no need to attempt to move everything to client-side, it doesn't make the UX better IMO, sometimes it makes it worse.
Keeping most logic and templates server-side works just fine on large complex sites serving millions of people, and it's significantly simpler and more stable for development than react or other frameworks, which seem to be in a permanent state of flux.
Of course, there are different versions of the latter: you can have an entirely client-rendered site, or a site that runs largely the same client-side code on the server for initial HTML renders (like React SSR), or a site that renders HTML from the server and then has separate client-side code to enhance interactivity, or any number of combinations of these and other approaches.
Not only that, but the “simple sites” that used to need a dev to build (like for a local restaurant or business or something) can now be done by the restaurant owner on WordPress.com or Wix or something without much effort
If you see no added benefit to having your page run in the browser, then by all means do things the old way, and you'll find that even doing the things the old way is today much simpler than it used to be.
If you do want to create a web application that for a large part runs in the browser, I can only see things getting better every year. The perceived added complexity is simply because we are now doing stuff that's more complex.
TL;DR: Building horse carriages was a lot easier than building autonomous cars.
Compared to all that, React is ridiculously simple - it has a very small API surface, different parts of your app are isolated by default and performance optimization is generally very straightforward. As somebody who really loves simplicity, React is by far my favorite UI library at the moment.
I think when people fondly remember simpler times with jQuery, it's not because jQuery itself was simple, it's just that they remember working on less complex applications.
Most websites (including this one for example) still function that way. It works fine. JS frameworks simply are not required for most of the work the web does nowadays - you can add interactivity and immediate feedback where it makes sense very easily with vanilla js.
In both cases, you end up with non-UI wrapper components to provide the plumbing in a tree of components that would ideally be entirely presentational. That leads in turn to trying to separate presentational vs. container components, trying to avoid nesting any kind of container component within a pure presentational component to keep it easily testable, creating more HoCs in an attempt to separate concerns, etc.
I certainly wouldn't describe React as garbage like the OP - but I think whether it's the best choice is heavily dependent on the kind of app you're building. The design choices it has made comes with significant challenges and trade-offs and we should not pretend otherwise.
I'm glad they're putting the effort into making the API simpler and easier to use to address some of those concerns, but React itself has been around for seven years now - the vast majority of existing developments will have been started using versions of React created before hooks were introduced.
This is why I stick with Vue. One <script> tag later you're good to go, and all of the extra stuff (like .vue files) isn't necessary to use the framework.
It's a godsend. I can't imagine how many hours I've lost to obscure webpack errors before switching.
Any production-destined app is going to have to go through some baseline transpiling, linting and minifying, and CRA really shouldn’t be giving you much trouble with the defaults.
You can do this with React
Just that some third party plugins are written in es6, it would be cumbersome if you need to support ie11 in a enterprise setting.
Also if you have quite a lot of vue components to load, it would take longer time than compile first with webpack in http1.
Have you considered getting a different job? (obviously easier before pandemic, but from the sound of it you have been in this boat a while).
I’m glad I made it to the end. Why use React for a simple JS-based app when you’re very aware of many reasons you don’t like it for this purpose? If you’re being forced or pressured to by an employer or even the entire job market, that’s not really React’s fault other than for existing.
React (at least many of the features and use cases you mention) is for complex applications and developers that care deeply about the hairy details of user interfaces. (It’s also pretty easy to use without a build step for simpler applications, but that’s another argument.)
With Hooks I’m happy in that most of the “business logicky” stuff can be split out into those and my components have returned to being pretty much entirely UI code - I don’t really use any of those weird in-between tags like <Query> anymore.
Transpilation will happen if you want to use new JS features at all. If you use React without JSX and not using any ES6 features, then you can certainly support old browsers without those transpilation steps - just include the compiled CDN-distributed script in a script tag like jQuery, it’s even advertised in the React getting started docs. Just turns out nobody wants to do that.
I agree that SSR is a crazy story though and I hope someone makes something better - but jQuery doesn’t really help with that at all, bootstrapping state from a different machine than the runtime and not incurring state weirdness/security vulnerabilities seems like a generally difficult problem, not a React-specific one. NextJS (and maybe prerender snapshotting) seems like the only decent options right now.
Respectfully, that's not at all what HTML is supposed to be, but even so, as it turns out, sometimes you do need state to drill pretty deep down (say you need an icon to be green if you're authenticated). So people started just passing state as props everywhere, but oh no that's an anti-pattern. So now people are using redux, mobx, or the context API to do essentially the exact same thing. Three new tools were developed by dozens of engineers to basically re-invent "global state." It's ludicrous.
If you want the hypermedia-concept of mostly static documents with links to each other, feel free to turn off Javascript or not use React.
If you’re using the web as an application delivery platform that works cross platform without installs and instant updates, then HTML is the base of your UI framework, and as such it helps to have predictability that frameworks like React offer.
Re state, for me the “bad thing” about global state is usually the same “bad thing” about jQuery-based apps - that anything can mess with anything. But all the solutions you mentioned, and especially the Context API, force components to declare their dependencies and update shared state in restricted ways, which makes that “bad thing” much less bad.
If you don’t like shared state at all, feel free to not use any of those, and pass around state throughout the app - but don’t complain to me when synchronizing state throughout your web app becomes a problem, or that boilerplate becomes a drag, because those are the problems these solve.
Even if your application is 90% non-interactive, the remaining 10% could end up introducing a lot of complexity only because browsers haven't advanced on that front at all in the past decade. And that 10% could easily outweigh the 90% when it comes to the architecture of your application - you get frustrated with the jumblefuck of JS littered randomly around to support X feature on Y page and so you just grab React and build a more manageable thing with it.
The standards committees for the Web have seriously dropped the ball.
Therein lies the problem, understandable as it is. If you're using React (or any other modern UI/MVw/whatever for that matter), you're still describing your app as mutating a grossly inappropriate scene graph of divs and spans held together with CSS tricks when your conceptual model is probably more adequately represented in terms of panels, fields, and canvases. On top of that, you pick about the weakest language out there, and over the course of decades, morph it into becoming more like a real programming language with runtime type info, accidental async patterns, decorators, compilation pipelines and whatnot, giving up the two benefits that JavaScript has, namely ubiquity and running OOTB on browsers by simple page reloading.
It's not an anti-pattern because of some abstract aesthetics, it's a pragmatic management nightmare in practice.
> So now people are using redux, mobx, or the context API to do essentially the exact same thing.
Not to do the same thing, but to improve management of it.
> Three new tools were developed by dozens of engineers to basically re-invent "global state." It's ludicrous.
Why is it ludicrous that engineering effort goes into solving pragmatic problems with how things that have always been possible are done?
Use your example of the icon that’s green if you’re authenticated. With React (regardless of whether you’re prop drilling or using something like Redux and context), you just update your state with isAuthenticated: true and the changes to green. There should only be one way to set that Boolean, and the icon will update regardless of where that Boolean is set. That’s all that’s meant by this concept of HTML being a function of inputs.
It’s true than a client-side React application could just do AJAX requests on component mounts (or in a useEffect hook) to keep that data in local React component state, and that wouldn’t easily translate to React SSR (because the server renderer can’t know when your component tree is “ready”).
But most complex app-style web sites are already going to need some global state management similar to Redux, where data fetched from the network is stored not in local React component state but in a global store, and when you have that (as well as a JS router, something else you’ll probably be needing anyway), the React SSR story really isn’t that crazy at all.
I’m finding it tricky to implement cleanly in my company’s fairly large React codebase, though I do think the fundamental problem is not a simple one and requires tradeoffs.
But there are popular frameworks like next.js that have pretty simple patterns (like getInitialProps) that can probably be adapted to any React codebase.
I don't think this is a React mantra at all. Maybe "everything is a function" would be a modern React mantra? Seeing how React code is mostly hooks and components, and both are nowadays generally written as functions.
JSX is not even required when writing React, by the way. It's just syntactic sugar.
> It's crazy to me that it's normal now to have like 3-4 compilation/transpilation steps when working on a simple JS-based app.
There's nothing about React that requires this. You can simply include the react.js script at the beginning of your HTML document and write all the React code you want, no transpilation required.
If you want to use JSX, then you need transpilation, but again, JSX is not required to use React.
While not required, most people use JSX + bundler, at least for anything that resembles a serious application.
npm install -g parcel-bundler
parcel ./index.htmlPeople developing on other platforms love to complain about the build tools on the web, but those same people only have the luxury of simpler build pipelines because they have greater control over the machines their code will be run on.
I don’t see React as having caused this problem in any way (feel free to include React via a script tag from a CDN and worry about the compatibility of your code yourself), and I also don’t see this as a problem that will go away any time soon for web development.
That all said, I do think it’s getting better - all the major browsers have switched to be auto-updating, so it’s feasible for many projects to drop support for IE altogether and only support ES6; if you manage your CSS in JS, you don’t need to downcompile languages like SCSS; the two of those together mitigates a lot of the need for sophisticated build tools.
Everyone keeps repeating this, but looking at a pile of 'createElement' calls is so much harder to read than just looking at a page of html.
https://blog.bloomca.me/2019/02/23/alternatives-to-jsx.html
If you don't want to use any of them, convention is to use:
const h = React.createElement;
I don't know of anyone who actually uses `React.createElement` directly.Personally, with all the other things needing a transpile step (TypeScript, and support for older browsers), I've just gotten used to having one in every project nowadays.
> from an architectural point of view, jQuery is by far their superior.
What do you mean by this? The architecture of the sites I’ve worked with has been much improved by React. jQuery mostly seemed to be used for direct, script-style dom manipulation, which you can do with plain JS these days. You did it in so many places across your app that it was impossible to tell what caused what change and it isn’t immediately reactive to data source changes either. So from an architectural point of view, it certainly didn’t help your code. React is solving a problems that jQuery doesn’t claim to solve.
If you’ve got a basic website that needs a tiny bit of interaction, definitely use plain JS. But if you need to build software running in the browser, you’ll run into the kinds of problems that jQuery and plain JS don’t solve out of the box. If you don’t use a modern library, you may end up writing your own state management and reactivity later anyways.
I think everything in this sentence is incorrect.
jQuery started out as syntactic sugar to smooth over the cumbersome and inconsistent DOM manipulation APIs in various browsers.
No one ever seriously says React is a replacement for jQuery. It was a replacement spaghetti-and-meatballs on top of jQuery, Backbone, Knockout, Angular, and whatever other frameworks were popular at the time.
> It's crazy to me that it's normal now to have like 3-4 compilation/transpilation steps when working on a simple JS-based app.
This has nothing to do with React. To get a sane dev environment, you have to do these steps even for a simple site. It's a consequence of browser standards moving slowly and of JS and CSS being awful.
If I can't write front-end code (even for a simple static site) with a decent Webpack flow, TypeScript, and SASS, then I'm doing a lot more work and delivering a lot later. Those tools can be buggy, but most of the time you can just stick with some boilerplate and not end up with anything terrible happening.
> Boy do I miss the days when I was building stuff in PHP and HTML was simply rendered when I ran the damn thing.
You can still do this with PHP (or any other server-side language). It's still a first-class citizen of the .NET world.
So at the core I chalk the situation up to people problems, not technical ones.
However, given websites aren’t the only use of react I strongly disagree with your overall sentiment.
My organisation uses react in place of desktop apps, and it’s been a game changer for us. We work faster, we train devs faster, deployment is easier, we can painlessly hit everything from desktops through iPads, and we make far fewer mistakes.
I really don’t see an alternative, at least outside SPA-land.
1. UX
SPAs do not offer native user experience and it's generally harder to provide it on all platforms at once, even with solutions like Cordova or React Native. Usability and accessibility requirements differ, interaction patterns differ, and sometimes you have to produce completely different designs on desktop and small touchscreen devices. On desktop specifically there's a rich history of rapid application development tools and UI frameworks aligned very well with platform guidelines and design patterns. Native development on mobile still beats everything else when it concerns UX.
2. Development
The development cost for browser-based apps and React specifically is definitely one of the lowest, due to popularity of this technology and availability of the tools. RAD and technologies like JavaFX can be inexpensive only if you already have the team familiar with the stack.
The development speed of RAD tools was and still is impressive when it concerns UI. The interactive prototype of a screen created in 15 minutes in a visual tool IS the application that can run. All you need to know as a developer, is the component library and programming language. I do not really see, how React could be better here. One big advantage of browser-based apps is ability to develop both for desktop and mobile platforms at once, but this has UX consequences (see above).
The architecture of native or imperative-style frameworks is generally better than of any of JS solutions. JS ecosystem tends to reinvent the wheel by gradually introducing best practices which are pretty standard everywhere else for decades. E.g. it took some time to build Redux, which is quite similar to the UI event dispatching mechanisms in Java and the like, but uses its own unique terminology - reducers, stores etc - for what is actually a combination of classic design patterns like Observer.
3. Deployment and support
One major benefit of SPAs is instant delivery of new version to all users, achieved by design, but the SPAs packaged in desktop wrappers do not even have this benefit. Also, is mitigated by the existing approaches on distribution of standalone desktop apps via update infrastructure (which also allow canary deployments).
One of the rarely visible costs of WebView apps is the resource consumption on the client, which is usually ignored by the developers of online services. Browser engines are not the most efficient VMs for running application code and they require A LOT of RAM. Just compare Slack and mIRC - similar chat functionality (Slack may have better support for rich content and integrations), but how different they are in utilization of resources!
Coz I use it every day, and despite many little deficiencies, it still compares well to other cross-platform toolkits.
You don't need a bundler. All the major browsers will run ES6 modules these days (https://caniuse.com/#feat=es6-module and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guid...). We use bundlers because we still target older browsers and a lot of library code isn't in a format that works in browsers yet (and probably never will be in a lot of cases).
React and optionally react-redux is more complex in itself, but it is really trying to tame app complexity you'd get with lots a jQuery sprinkled around. With react, you can reason about the state of the app, and know the current view is calculated by a (hopefully!) pure function f that maps state to the view.
Don't really see the issue with HOCs. I am not seeing why they are a terrible idea. I think they are quite elegant actually.
SSR I might have to agree with you. I haven't yet understood why it is needed honestly. Is it SEO or something? Or is it speed of deep linking into a 'page' of your SPA.
As for the compilation steps - meh. This sort of stuff is done a lot on the back end in larger projects too - pre compilation steps and wat not. It's not a big deal with a bit of webpack watching.
* jsx: I've been very open about the utterly flawed notion that html should be treated as assembly or cobol: something that only old people with long white beards know and use. As a consequence you have to rely on post-market plug ins for your browser just to figure out where element X comes from. As opposed to what the "old people" would do: grep -rn {pattern} which will genuinely give you the answer in a few seconds tops even for even the largest of projects. As opposed to clicking your way through tons of elements in a browser and staring at a second screen to figure out which is which.
* The endless "compilation" just to get something show up on the screen. Not to mention the ridiculous amounts of system resources required to do said "compilation".
* 5-6mb js files. Holy crap!!!!!!!!!!!!!!!
* Everyone's obsession with mocking data. This is in all cases a terrible idea and leads to tons of "well it works on my machine". In essence you end up with two different applications, one being the frontend and one being the backend and you rely on getting everything right and magically turn that into a "they lived happily ever after". Well... That happens only in fairy tales. That's not to say you can't develop both in parallel without mocking data but for some reason I've hardly ever seen people do this.
IMO, the web is turning into a bigger mess than ever because of this. Even bigger than the flash and coldfusion days. IMO all of this needs to be scrapped and re-done. There have been plenty of attempts to replace js with something that is not garbage by design. But all those attempts were greeted with "No, U fragmentin DA web!!". Well yes, naturally. The point of a migration is to slowly ditch a horrible X for a better Y. Annoyingly, because of this, just like react, it seems js is here to stay.
A real shame really, given several much better alternatives. For instance, I used dart(pure, clean dart, no frameworks or anything) to build my personal page and while I still had to rely on transpiling, there's a strong type system which behaves as you'd expect and pure html and markdown. Yes, even for a simple thing, the generated js is 90kb gzipped but given it's entirely self-contained, no additional code needed and renders markdown out of the box, I'm fine with it. Is it ideal? Hell no. Can I add or remove stuff on the go if I ever need to? Absolutely. I may not be able to add an entirely new functionality while I'm hiking or whatever but add a link or something small and trivial without having to install a ton of crap or have a complex ci-cd setup?
1. vim a.html, add X.
2. git commit && git push.
And just like that, 15 seconds later I'm back to hiking. My argument here is that with some additional tweaks, things like these would be significantly more useful and manageable even for large projects than the huge lumps of fat that the "modern" frameworks enforce us to use.
JSX isn't HTML, it's an HTML-like syntax for JS (it's essentially XAML for JS), and React doesn't have a mantra of “everything is JSX”. It has a mantra of everything is JS, and some of it is conveniently expressed in JSX. It does strongly favor a declarative, functional style whether it's expressed in the form of JSX or conventional JS syntax.
> SSR. I've brought this point up on HN before, but doing server-side rendering in React is absolutely ridiculous.
Yeah, it's basically a client side SPA library. You can do SSR with it, and it supports it, but that's not really it's happy place.
> Boy do I miss the days when I was building stuff in PHP and HTML was simply rendered when I ran the damn thing.
PHP is still around and widely used. If it fits your needs better than React, use it.
> As author points out, what in the world does a <Query> tag even do?
This is not "React". This API was Apollo's decision, but just like you see libraries that lean heavily in the "everything is a component" direction, others don't. I personally use and like React quite a bit, but find this heavy use of HOCs in some 3rd party APIs a little weird.
> And everyone just bought into it because the guys at Facebook must be really smart.
Facebook builds and uses Relay which doesn't do this, which doesn't use HOCs like these ones Apollo does.
> The lifecycle hooks are just confusing and unnecessary.
It's fair to call them confusing if you feel that way, but I don't think you can say they're objectively unnecessary. They've all come pretty handy at some point or another in my use of React. Learning the lifecycle of a React component allows you to effectively integrate it with libraries that were never built with React in mind— I've used D3 + React extensively and and being able to do different D3 operations at different points in the component lifecycle makes it all work seamlessly.
> they change every few versions (so old code will inevitably break on new React versions).
Do they? React is pretty good about backwards-compatibility as far as I have seen. Wasn't the last breaking change with the release of 16, like 2-3 years ago? They also tend to make code-mods available to automatically migrate things, which can come in pretty handy.
> Boy do I miss the days when I was building stuff in PHP and HTML was simply rendered when I ran the damn thing.
I do miss this too (although it hasn't gone away!), but this is not endemic to React. It is really is a traded-off to make when choosing to make a site rendered by JS (with all the advantages and disadvantages it brings) or the server (ditto).
"The way I like to think of it in comparison to Angular is this: Angular is a framework for architecting and building applications. It, for the most part, doesn’t change the way you write your HTML or CSS, but it heavily controls the way you write Javascript.
React, on the other hand, is a library for building user interfaces. It, for the most part, doesn’t change the way you write Javascript that isn’t directly related to your UI, but it heavily controls the way you write HTML and CSS (or the equivalent of it). And this brings me to the next point…"
I don't use Redux or server side rendering - they're not needed.
The only thing that I think it should do differently is leave styles to be handled natively.
To my knowledge, React itself has no opinion on styling. It's more the ecosystem around React that's gone css-in-js.
But, yes, if you want to do your styling natively that's really not a problem.
There was no; tool chain, bundling, virtual DOM, render function, countless layers of library abstraction, sourcemaps, node_modules... etc. Just a simple index.html file
Some projects don't require a state of the art virtual-DOM-diffing-machine, just to display a list of ToDo items...
When the only thing your application shares with its dependencies is its view renderer, you're going to feel a lot of pain. This is one of the big reasons why I use Ember.js for complex web-frontends (though holla to phoenix live views). It's a framework-- it has all them pieces you need included in a sane way that's consistent.
Just my two cents...
P.S. If you write JavaScript UI code, and you want to like be better at it, go write native UI code. You'll learn soooo god damn much, write better JS, and understand a lot more about what the fuck all these pieces (like react) are actually doing (rendering UI, managing state, networking etc) in a sane curated (thanks Googs, Microsofties, and Apples) way.
And in practice some state is specific to some component or group of components and some state is global or the group of components doesn't translate to a subtree of HTML's tree structure. Also the kind of thing that has to happen based on what happens in the app is often deeply async.
And it all becomes a mess.
But it's still not as bad as a mess as without React, I believe at this moment.
You lost me there.
Cute for a solo/learning project, but when other people are touching the project or you're trying to build a business, you have to answer for why your project was so special that it needed its own ad hoc framework. As opposed to, say, a framework with real documentation. Or one with an ecosystem so you can escape this culture of NIH.
When I hear someone building their own JS framework, I see someone who wanted to procrastinate the hard part (building a business, shipping a product, appealing to users). Like when game developers decide to build an engine and never make the game, aka the hard part (https://www.voxelquest.com/).
They say it often but it's not true. React forces you into an entire workflow with JSX, bundling, source mapping, babel transpilation and often restricts you to using components that are designed specifically for React; accessing the raw DOM is nasty business.
If it was a library, it would not hijack the DOM and override it with its own; that fact alone is more than enough to call it a framework. Any tool which takes over the execution environment is a framework by definition.
A library is something you use, a framework is something you work inside. You could argue that react could be used to target only specific components but this would be missing the point that 99.9% of the time, React is not used like this; as soon as you have a hierarchy of components, it's a framework, not a library.