React is 10 years old
twitter.com
twitter.com
I learned jQuery long ago, then how to get most of what I wanted done via document.querySelector/etc instead since it was more "lightweight", then I learned React "class components" with render() and componentWillMount() and it was a big leap forward.
The "major breaking changes" (semantic versioning wise) to move components to functions (instead of implying it's just a class with render()) and then hooks on top, it almost invalidates most of what I learned about React initially. Which is fine. The community reserves the right to grow however they want. I was just surprised when I recently revisited it. The only common concept was basically JSX and "view/render state/props + actions on events".
I don't think many would agree to this but I'd argue the changes are so radical that they almost should've called this new React something entirely different. It would help. Saying "I know React/I have React experience" is basically in need of nuance like "I have React in 2018 experience, and 0 React in 2023 experience, therefore I don't actively/actually know current React best practices or how to even do a small TODO hello world list example".
EDIT: I'm referring to how the proper use of useEffects is to almost never use them. They're for side effects, and they're not a tool to just "re-render when these dependencies change". But to do this right, it requires a re-wiring of the mental model of how to do React, at least for many people I've come across.
Some of this predates the introduction of hooks, as much of the useEffect misuse is identical to the way people misused componentDidMount/componentDidUpdate/componentWillUnmount.
I don't think you're right to say that you should almost never use them. You should use them for doing the things which they're designed for, like attaching event listeners or dealing with timers (neither of which are that unusual in my experience). But like I said, they've never been a tool for dealing with rerenders, and the React team has been trying to explain this to people for ages. The original docs did explain this, but it was less clear than the new ones.
Edit: here's the video (from 10:20) https://www.youtube.com/watch?v=nYkdrAPrdcw
I was using useEffect, with the deps being the things sent to the query.
The new docs emphasize this, I guess mostly to make users think twice about building their own hook and to make it easy to move initial data fetching to the server.
Frameworks include next.js, remix or vite-plugin-ssr (the last one is maybe an outlier, as it deems itself a library).
Often fetching is tied to routing, which makes sense.
If routing is not needed, AFAIK the go-to solutions right now are react-query or SWR.
react-query has a nice comparison table for data fetching libraries:
https://tanstack.com/query/v4/docs/react/comparison
If routing only takes place on the client, react-router also includes data fetching features:
https://reactrouter.com/en/main/guides/data-libs
I don't know how well react-router fits with SSR.
If none of that fits and the requirements are either very simple or very custom, it should still be possible to manually pass props to the root component.
Looking this up in the docs, the big caveat of this unconventional approach is that props would not be reactive, the root component would have to be manually re-rendered:
https://react.dev/reference/react-dom/client/createRoot#upda...
One of the sources of confusion I see the most around effects is that people still think of them in terms of components mounting and unmounting. However, effects only care about running, cleaning up, and maybe needing to run again. I can't think of a case when they'd need to know about the component's mount/unmount behavior.
For effects, the main things to consider are:
• Can this effect be fired unconditionally, and if not, what could change in the system to make its result inconsistent/outdated with the new state of the system?
• What cleanup does this effect need?
And this would have been fine if they had been upfront about how they were wrong about useEffect and how now this is the correct way to do it. But instead, they’ve at best kept silent about this transition, and a lot of people strongly attached to React have decided to gaslight everyone else about useEffect (I’m a huge React fan… it’s my default UI library but that doesn’t mean I’m ok with gaslighting over transparency).
And the easiest way to prove this is to compare the docs.
Original: https://legacy.reactjs.org/docs/hooks-effect.html
> The Effect Hook lets you perform side effects in function components:
New:
https://react.dev/reference/react/useEffect
> useEffect is a React Hook that lets you synchronize a component with an external system.
Synchronizing with an external system is completely different behavior from performing side effects. And we know the original intention was to perform side effects and not sync with external systems because the name of the hook is useEffect and not useSyncExternal.
Unless the React team always had the new intention but deliberately decided to mislead everyone through the original documentation and by misnaming the hook, but I don’t think even the biggest React hater thinks so poorly of them, and I’m a fan.
And I do think the team has been refining this conceptual territory as they go. React is a pretty unique programming paradigm at this point, there's lots of uncharted territory. Following Dan Abramov on Twitter, he works through concepts out loud, having new realizations about how the primitives they've created fit together, what their implications are, metaphors for thinking about them, in real-time. I think they've got a very clear direction at this point, but they haven't turned over every stone along the way yet.
I've compared the docs, and I don't think that's clear at all. They definitely refined their messaging, but the legacy docs show the same sorts of examples that are either shown in the new docs or described[1], such as subscribing to an event system or updating a bit of non-React UI. Could you give some sort of example usage that they encouraged before but don't now?
No, synchronizing with an external system is exactly performing side effects. It is a change in document focus from a description that focuses on what it does to one that focuses on the purpose for which it does it, but all synchronization with an external system is side effects and the vast majority of side effects that aren’t incidental to imperative program structure (which functional components avoid) is syncronizing with an external system.
I haven't tried asking GPT4 a bunch of react questions yet. I wonder if its advice is generally in accordance with the "new way", given the training data cutoff date.
Having components with lifecycle methods called at known times by the framework is a perfectly straightforward mental model. It's worked just fine since the beginning of time. iOS still uses it.
I remember investing hours (and days and weeks) migrating old code to the "new way" or trying to get some simple thing "working with hooks." Other than being able to share in the authors' feeling of smugness over the unnecessarily-convoluted mental model when we finally got it all working, I genuinely can't recall any value we got out of the whole investment.
In the end, hooks have greatly simplified things for me.
Android, too.
So are the users wrong, or did you screw up?
When you have to rewrite the documentation to basically tell the world "you're holding it wrong" then it says a lot about the thought that has (not) gone into designing the feature.
And that's why I think I'm done with React for now. It just does not spark joy.
If you're not properly tearing down what you're doing in an effect, you're just making room for bugs.
These have always been true of useEffect.
If anyone reads this and I am wrong please comment, but from what I can see that's the only solution.
As far as I know you can still trundle on with some of the old react, but at the same time, things change. It’s not like you’re coding C# similar to how you were 10 years ago either. I know that having been away from it, it was interesting to see everyone using “var” instead of types as an example.
A component that has some state associated with it, such that manipulating that state causes certain side effects, seems almost custom-fit for OOP. The functional style does not seem to fit the domain.
Try stepping outside of JavaScript for a while, broaden your experience.
> Classes and types and methods exist for a reason.
What that reads like to me is actually the exact explanation as to why the JS community has fallen out of love with things like classes. Because JS doesn't have static types, and without those, well... Classes don't actually exist. At least not in the way they do in other languages like C++. You can pretend you're working in a regular OOP language, and use the prototype object like you would a C# or Java class but since you don't have static dispatch at compile time, you're frankly playing this part of JS as a weakness instead of a strength.
Which is why the JS community has been "growing beyond" classes.
If working with classes in JS is more comfortable for you, then I think you should do so, but ultimately a JS class is just a function. Once you grow comfortable with working with modules and functions, you're very rarely going to be writing classes when working with JavaScript. You're still going to do so from time to time, when it makes sense, but often its both unnecessary, less efficient and harder to maintain something that is build like a C++ class rather than than a JavaScript function. While working with JavaScript, being a key part of it. This is not an attack on OOP in general, just an explanation as to why the JS community has "moved beyond" pretending JS is an OOP language the same way Java is an OOP language.
> Try stepping outside of JavaScript for a while, broaden your experience.
I do so regularly.
If a thing need properties and methods to operate, defining it as class won't make it harder to maintain than cleverly do it with functions and object.
This would be true if JavaScript had static dispatch, but since it doesn't, everything you do with your class is mutable all the way up the prototype object chain. One of the reasons this is harder to maintain, is because the "strictness" you think you build into your code isn't actually there unless everyone who works on your code after you follows the same rules you did. I'm sure we'd like to live in that world, but I doubt we will.
If you want something more, better to use TypeScript or step to something like Rust+Wasm.
JavaScript is a prototype-oriented language.
Again you're basically speaking into exactly what I'm trying to say. Because what are JavaScript functions? It is also a prototype. I'll try to put it a different way. The JS community has "moved beyond" classes because they are functions. Both classes and functions are prototypes, but functions are often easier to work with, more maintainable and more efficient.
I'm not trying to say that you should never write another JavaScript class in your life. I write them myself when it's prudent to build things in a structure that resembles classical OOP. The reason I don't personally use that sort of coding style, if I can avoid it, is because it's an act. It looks like classical OOP, but everything is mutable at any time which means it's very easy for consumers of the code to break it by accident. This is less of a problem when you build things as isolated modules, based on individual functions, because there simply isn't any complexity to "misuse".
This is sort of similar to why the virtual DOM became so popular in frontend JavaScript. Because it's harder to work directly with the DOM itself. It's not necessarily better to use functions, it's just "safer", because they come with less risk of someone doing something bad by accident down the line.
Is this what $200/hour consultancy looks like?
To fill you in on the context of the thread you inserted yourself into, classes have fallen out of favour _in JS_. It's pointless to say "but they're still used in other languages!" because we're not talking about other languages, we're talking about JS.
You can choose to write functions for everything, but you're still always using object prototypes.
There are several large popular libraries in JavaScript which do not orient themselves around functional object orientation, too. So you might work in one corner of JavaScript where all you experience is functions, but that's not the case everywhere.
They haven't "fallen out of favor," whatever that means.
Just because CS has heavier weight classical structures we can apply doesn't mean they're better. And underneath a lot of those ideas were more lambda-calculus ideas that correspond somewhat with functional components.
You can STILL write React like you used to (with class components). There haven’t been any major breaking changes. The transition was very slow. It was only recently that they even changed the docs.
You’re complaining that they made changes to it half its lifetime ago after you walked away from it and now you can’t just go back to the way it was.
I firmly believe that FP-seepage into web programming is one of the reasons why so many web apps are so slow and feel sluggish, jittery.
Redux mainstreamed the concept of reference changes triggering updates, but I think this is a horrible pattern - we don't even have an operator in JS for explicitly passing by reference, so you end up destructuring large objects constantly in order to change one property and create a new object reference, which is a totally inefficient alternative to calling a render method. Plus javascript developers don't generally think about the concept of passing by reference vs value anyway, in large part because the language gives us so few tools for making those choices.
As a result, there is a class of bugs where the only solution is to change the list of dependency variables for a given hook. It doesn't take a huge amount of complexity for the implications of those dependency trees to bend the mind, and the "clean" syntax of hooks comes crashing down.
> there is a class of bugs where the only solution is to change the list of dependency variables for a given hook
++ it does seem to cascade from there.
Instead nowadays people who started with the function form don't know shouldComponentUpdate ever existed and all their React components constantly rerender.
Wouldn't you expect jQuery to keep using the same fundamental methodology a couple of years later?
Not only React changed completely almost overnight, but the changes in the methodology were fundamental.
If they had just made a different project, we’d still be talking about the same thing. You would still be complaining that things changed and you didn’t feel like bothering to learn a new thing.
But lambdas and everything coming in project amber, yeah, there will increasingly be many styles of Java out there.
Based on my experience only once CompletableFuture was added to Java did the Future interface really start getting used in mass. Before that, there were other libs that implemented Future like things (Rx, Guava, Netty, etc) but they were not adopted across the board.
The transition to Java 8 was night and day! Roughly on par with the React Hooks transition.
So, what stayed the same?
* Could still use classes
* Still had the same props & state semantics
* Components still could own state and receive props
* Some renamed code paths were used, a couple of the "componentShouldRender" style ones were dropped to prevent programmers making fatal errors
* Still wrote the same markup
* Still could use the same libraries
I never really understand this complaint; React achieved gold standard backwards compat. Either that or my 2016 era tools building in 2023 on the newest React with old ass libraries would've caused a lot more pain points!
The formal way of using React and JSX without a full SPA framework is only listed here: https://legacy.reactjs.org/docs/add-react-to-a-website.html
> If you want to build a new app or a new website fully with React, we recommend picking one of the React-powered frameworks popular in the community. Frameworks provide features that most apps and sites eventually need, including routing, data fetching, and generating HTML.
> Grab react and react-dom from npm, set up your custom build process with a bundler like Vite or Parcel, and add other tools as you need them for routing, static generation or server-side rendering, and more.
https://react.dev/learn/start-a-new-react-project#can-i-use-...
You can still write React the old way.
I don't even understand the reason why class-based is "legacy". Why are hooks inherently better? Code-reuse is a factoring concern, not a paradigm concern. And component-life-cycle bugs are now replaced with nearly impossible to understand callback stacktraces.
It's like saying "All Javascript things I search are only in ES2020." It doesn't mean javascript is deprecating features.
Absolutely and I've been saying the same thing for years.
IMO it was an extremely irresponsible thing to do considering React is critical infrastructure at this point. And by completely changing the methodology they made obsolete A LOT of educational content (books, tutorials, videos, etc) in an instant. I'm sure people making money of React education were very happy with this.
Don't get me wrong, I'm not against evolution. But if you're going to make such a drastic change just create a new project. Plus I wonder what other improvements/changes they could have made if they had started from scratch.
The react devs made a bunch of code migration tools, used semantic versioning, slowly deprecated old APIs over multiple versions, maintained vids and documentation. Honestly compared with some projects they handled the changes and evolution of the API extremely responsibly.
God forbid you're a principal running into some junior engineers and they don't understand that you've forgotten more than they know, and the migration to functional components is just another part of your extended career timeline.
in practice, pick your battles.
Also then in practice, you'll get people shrugging off their hooks get called 10 times iso 1. then maybe add useMemo everywhere just to be sure. Hmm.. still kind of weird. Maybe sprinkle in some more if-thens, that will fix it! Deep breaths..
"useMemo is the solution" many will tell you. Compared to the way things are handled in Vue, useCallback and useMemo are near enough code smells for something rotting in the center of the React codebase.
If as a principal, you are no longer able to keep up with tooling / patterns that everyone else at your company wants to use, its time to take a smaller scope or time to retire.
The job, including mandates (if any are needed) is to empower the people you work with, not to stifle them.
From my experience its not learning something new thats a problem, but getting the organisational support to push a major change through
Nobody is talking about that. Instead is about how these changes could be done without creating so much confusion in the community. In fact people embrace evolution of these frameworks but with clear changes in methodology, labeled as such and so on.
This argument goes out the door if you need to adopt a library that has already adopting them.
Even reagent, an extremely conservative React wrapper, had to provide support for functional components, hooks and effects eventually.
1. You can use both styles, even interchangeably.
2. The latter is superior.
Async/await allows you to write asynchronous code in a synchronous style.
Hooks allow you to write stateful code in a stateless style.
I'll draw an analogy.
---
Why did async/await replace callbacks? They are really the same thing, aren't they? Aren't callbacks good enough?
Async/await allowed programmers to write asynchronous code as if it were synchronous.
---
Why did hooks replace classes/imperative? They are really the same thing, aren't they? Aren't classes/imperative good enough?
Hooks allowed programmers to write stateful code as if it were stateless.
function MyComponent() {
const [value, setValue] = useState(false);
const buttonClass = value ? "on" : "off";
return (
<button
className={buttonClass}
onClick={() => setValue(!value)}
>
{String(value)}
</button>
);
}
This is functional code, without scary, hard-to-reason side-effects. Except for one limited part, which operates in a stateful way.I argue that this is simpler than the equivalent imperative-DOM modification code, and the gap between these only increases with real programs.
This isn't just a weird "web bro" thing; the hooks paradigm is useful (in theory and practice) to every UI platform.
I even wrote an implementation (closed source) for hooks in Angular. It was lovely.
It is some pseudo DSL with hidden hard to reason mutable state.
let result;
for (const item of items) {
result = await foo(item);
if (result) {
break;
}
}
is not synchronous code. But you can write it very close to the mental model of synchronous programming.The same is true of hooks. The code is not stateless, but you can write it very close to the mental model of stateless programming.
That is why -- despite them being optional -- hooks have become incredibly popular.
It also shows that although there might be some learning investment required to use the more modern version of both, it's well worth the effort. I can't imagine going back to callback-riddled javascript
I don't know exactly how – never had the time to properly research it – but, my current guess is that the hooks code taps into the scheduler/dispatcher – which handles the execution of the function representing the component – and stores value and logic somewhere. It uses the order of these calls as keys – you don't have to specify them – and provides the stored values as return values of the call of the hooks functions.
Hooks are escape hatches from the functional paradigm of React's components. You are always providing new values, and it decides when to store the updated version – mostly based on the deps array. You then get back what you stored. On the surface, it's still basically functional, but the actual logic is not. It's more like a repository of code and values.
It's still so very functional programming-inspired, even if the execution engine (scheduler/dispatcher) isn't that much like the Monad runtimes of most functional programming languages and the various Hook "monads" don't get captured in even the return type of functions (much less the parameter types) and get elided away. (It could be more "traditionally JS monadic" if it [ab]used async/await syntax and needed some fancy return type, even though the concepts for hooks don't involve Promises [or Futures, being the slightly more common FP Monad name]. Though also, from Typescript patch notes, I've heard React is exploring [ab]using Promises for something like that in the near-ish future.)
Monadic bindings needing to be in-order, just the like "Hook rules", isn't even that strange from an FP perspective: there can be a big difference in which of two Promises is awaited first. There can be a big difference in which IO binding executes first (you don't want to input something before the prompt of what to input is printed).
"What's this .map() nonsense? The indexed for-loop always made sense to me."
It isn’t only front-end developers who are prone to this: 20 years ago, before FP became a mainstream thing, being able to do pointer arithmetic was seen as the differentiator between a “smart programmer” and a “bad programmer” (https://www.joelonsoftware.com/2006/10/25/the-guerrilla-guid...).
Was React great and fun to work with? Yes, but then Redux came along and made something simple into something stilted. Our team used Mobx instead, which was simpler IIRC.
Similarly it’s been a couple of years, but I remember React Hooks being a bit complicated for the value we got out of them.
Ultimately, it’s hard to tell if something is an improvement, or a time suck to allow the elites to stand out. I stopped playing the game and stepped away from front-end development, as have many of my experienced colleagues.
I’m assuming things have settled as Big Tech focusses on profitability rather than funding an endless parade of frameworks, and the IQ-signalling will become less prevalent as generative AI competes with the brainiacs. When that happens, I’ll dip my toes back in the world of front-end development.
Though FWIW, MobX is far more magical than hooks.
That’s the magic of react. The problem is no longer manually managing transitions between state but state itself.
That’s why state management is so critical in the react ecosystem.
Further, react has delegated two key features to userland: side effect and state management.
Personally, I don’t want react to solve either of these problems because it’ll just turn into the disaster that is react server components: feature development driven by corporate interests (eg vercel).
If this was actually how it worked, I'd have much less problem with react. What I mean, specifically, is that not all function dependencies are explicit. This makes it look like the state is passed into some function. And then the view is returned, depending only on state. In reality, half the state is passed in (as in the argument to a function call), and half comes out of some mysterious hook storage structure. If the state was really a function argument, you could easily inspect the whole state in a debugger. Instead of... I'm not sure how you'd actually do that.
if you've followed along with the react team's discussions on server components, it is very clear that vercel implemented the react team's vision and less so the other way around.
as someone who has been using them extensively, I understand why. they're delightful.
vercel does control next.js which is the only framework to completely implement RSC, but as other frameworks catch up, RSC will have a wider surface area.
Here's how the React docs introduce it:
"React is a JavaScript library for rendering user interfaces (UI). UI is built from small units like buttons, text, and images. React lets you combine them into reusable, nestable components."
Hopefully you can appreciate the difference.
Hopefully you'll click on it someday
2) Components have behavior. In Class based components they were implemented as methods. Simple enough, classes have methods. If you think about an iteration of rendering the ui tree, it goes down the tree and calls the mount method for each component in the ui. With hooks, instead of calling a method on an instance, it's implemented as an inner function of a component that is also a function instead of a class. Instead of explicitly calling the mount method on a class instance, calling a function that's a component automatically runs it's inner mount method. The way that it knows the which inner function is a lifecycle hook is because you import something like 'useEffect' from the react library. And that global useEffect function knows the current component because the renderer sets it as it's going down the ui tree. Hooks are better because they can be written as arrow functions (more concise, cleaner), and because you're calling a framework function, that function can have more complex behavior like how useEffect can track when to update because it's being passed in an instance of something like an internal state variable.
https://nakedjsx.org/documentation/#getting-started
EDIT: clarity
That sentence didn't end how I expected it to. Personally - coming from a similar (jQuery -> Knockout > Backbone > Ember > Angular 1 > React > Svelte) background - I feel React has gone the same route as the others - rose quicky, dominated, and will never go away, but no longer has any influence. The same will happen to Svelte in future.
Not in the sense that React itself is functional or declarative (it isn't albeit its roots are in Ocaml), but the style of programming it introduced to many millions of web developers made a sizeable chunk of them interested in fp and many of those percolated to strictly typed FP in TS, Elm or Haskell.
Pretty much every major fp language has tried to implement their own declarative UI after React's success, be it for terminal applications or native development.
I myself fell in love with functional programming in part because of many of the concepts I was introduced to by the likes of Dan Abramov and company.
It led me down paths of research I wouldn't have known to go down, all the way back to the dawn of computer programming.
I feel that AngularJS (v1) did that years before React, and maybe even other MVC frameworks before that.
I can't think of anything React brought in that earlier frameworks didn't already have in a form or another. Maybe hooks? Arguably the worst and least performant part of React.
It only popularized "HTML-in-JS" but that has always been possible via strings or file imports. Even template pre-compilation was part of Backbone or Ember (I don't remember which)
Angular markup lives in templates which are used to generate and update the UI, while React markup lives in expressions which evaluate to values. This is a subtle but key difference. I would argue React isn't even an MVC framework (though it sorta pretended to be one for a while)
The virtual DOM existed only in a library or two that you had to build around, before React made it into a useable framework. The whole "automatically figure out minimal DOM changes", especially things like reusing existing <input> elements so the user input doesn't vanish or the element lose focus, were pretty much brand-new when it came out.
Why would that be? React is not functional, and the style of programming has nothing to do with functional programming. It is fundamentally inconsistent with functional programming.
> Not in the sense that React itself is functional or declarative (it isn't albeit its roots are in Ocaml)
At the beginning of React there were two different components: class-based and pure functional components. Pure functional components rendering has always depended _uniquely_ on its props. No surprises. This introduced a very large number of developers to indeed a declarative/functional style of programming which only depended on the inputs in an era when components were written with local state. Several libraries like Redux, which was Elm-inspired, further introduced millions of developers of combining a declarative/functional/reactive paradigm with handling state without mutations but messages.
Context, then hooks and other features broke this paradigm, whatever is the final result does not depend anymore uniquely on the inputs. React team believes the net result is positive.
I myself with others who commented in this thread and plenty of people I know where introduced to this style of programming with React and then migrated to more strict libraries in the TypeScript ecosystem or other languages such as PureScript, Scala, Elm, Haskell, etc.
The sheer number of flux frameworks were a testament to how underserved the state model was at the time. And without consistent support for async/await to make Promises work well in an app, data fetching and state was the worst part of React.
I’ve always despised Redux and the circus that came with thunk generators. MobX made things a little bit easier. And Baobab was a fun concept to bring Clojure-style cursors to JavaScript. It wasn’t until React shipped the context API and hooks that I felt the problem of, “how do I get this state from up here to down there?” was truly solved.
Personally, I’ve wished I could quit React for something like native Web components, but I feel like I’d be back at square one with state management and stringly-typed templates. Maybe Lit-HTML will get there one day!
Hooks and the context API are just different ways to manage state (and many would argue better). Do you disagree?
Most of my use cases is to build internal tools. But the pace with which once build things in react and its over intuitiveness just makes it special.
React is one framework which Im sure will be available for long time to come!
Thank you React dev team.
> and "keep scripts separate from your CSS and HTML markup"
was for documents, not interactive applications, with the goal being that a document could be reformatted through CSS for multiple different displays. The earliest example I can recall was web vs print (as in, in the browser go File -> Print; you can specific different CSS rules so the page prints differently than it shows in the browser). Screen size / mobile displays are other examples that came later.
React on the other hand is great for interactive applications, which have always worked component-style - a checkbox or a dropdown in a native GUI would be used multiple times and knows how to style itself, for example, which is the same as what a React checkbox or dropdown would do.
> "don't use inline styles"
This rule was broken simply because there wasn't a better way to do the component packaging at the time. Nowadays we have CSS Modules, which separates them again.
You've a function that returns JSX which is your HTML where you can use Javascript to reference functions/variables (e.g. the state variables)
One of the key parts is that you can break it all down into different files/functions that return jsx so you can isolate complicated parts
Before, I could call myself a "full stack dev" because I could cobble together a site with JS, but it wasn't pretty. It didn't follow any real conventions, was a nightmare to maintain, forget about testing, etc.
After learning React, I actually can design, and structure the code in a logical way. Testing is a lot simpler, code reuse makes sense... it created a mental framework on which I could translate my ideas into usable code that pattern matched to how I was used to building code for the backend.
I will never feel like I'm a "frontend dev", but I don't need to be. I can take an idea, and turn it into a functioning service, and isn't that all we're here to do anyway?
I’d used it before to trial it and explore differences, but never actually built something. I used it with XState (state charts) to build a version of Minesweeper which uses the receptionist pattern to orchestrate actors, which was pleasantly unnecessary, and I really loved it.
Although I have around 8 years of experience with React, Solid somehow made the process easier in some regards. React — despite being excellent in many ways — has a few sneaky foot guns that I still manage to wander into when trying new tools and patterns. Solid on the other hand was quite friendly. Ironing out anticipated performance issues was mostly an idea and never became necessary. In React I did need to tidy up some redundant renders and fix state synchronization due to out of sync effects.
I’m currently job searching and totally wouldn’t hesitate to work with a team that uses Solid. But, React is good too. At the end of the day I just love making things people enjoy using.
And with react having to fudge with the state of DOM input components, it's been a messy ride.
And yet, the idea of describing your UI and have a library figure out what needs to be repainted has been liberating. React certainly wasn't the first, but it certainly was the most elegant one at the time.
I wish React would split up and go back to the roots: Have it deal with rendering - and nothing else.
Have optional companion projects that deal with the various forms of state and side-fx.
I really wish React would just own the low level forms stuff and get rid of the need for a 3rd party form management library. That said, because it is frontend JS, there are 1000 different ways to bike shed this problem and because it is form stuff, there is no one solution that fits all use cases.
I was somewhat skeptical in the early days of React, but once static websites with rehydration became a thing, I was fully in. So much power.
Not really. See a better way here: https://github.com/wisercoder/eureka
"Lucene based search" vs React ? Seems like comparing trees to tractors.
I've read the web app and it seems to me it is just https://backbonejs.org/ re-written in Typescript and allows JSX.
I'm very certain Typescript and JSX will have improved the DX for Backbone like apps, but it doesn't address all of the other issues that teams had with Backbone.
e.g. Cyclical event propagation, state stored in the DOM (i.e. appendChild is error prone in large multi-person code bases), etc.
FWIW, the reason this works for eureka is highlighted best on this page: https://github.com/wisercoder/eureka/graphs/contributors there is only a single author!
The style used is MVC. Do you think MVC is not suitable for multi-person teams? If so how do you explain MVC in Cocoa, ASP.NET Core, JSP and JSF, Ruby on Rails, and Django (Python)? They are all based on MVC.
Cyclical data bindings and two-way data bindings are fundamentally different issues. Not knowing the difference makes it pretty clear you haven’t lived through a codebase that had these types of issues.
MVC seems great in sprit and breaks down at the first real interactive, stateful usecases.
> Do you think MVC is not suitable for multi-person teams? If so how do you explain MVC in …
Correct, I do not find MVC suitable for multi-person teams. You won’t believe me, but it is an incomplete abstraction that was previously relied on but since React and also modern video game engines it is no longer in favor.
Why is it still used by all those legacy frameworks? Because, frankly, they are old and haven’t evolved.
Apple has moved on from Cocoa to SwiftUI. Java devs have all but moved on from JSP (goodness those days were terrible). Rails for all its awesomeness has been stuck for years not able to move past itself and typically now paired with React or Vue.
MVC was a good stepping stone, but now we have learned and we are moving on!
> Sorry none of this makes any sense to me.
If you're not familiar with the MVC variants (MVVM, MVP, MVI, MOVE)[0][1] we should start there.
Next you should read through some common mistakes of Backbone.js like applications https://www.toptal.com/backbone-js/top-8-common-backbone-js-... and some criticisms of MVC on HackerNews in 2012[0].
Finally if you haven't before these talks, they are the ones that sold me on React:
- https://www.youtube.com/watch?v=-DX3vJiqxm4
- https://www.youtube.com/watch?v=DgVS-zXgMTk
- https://www.youtube.com/watch?v=nYkdrAPrdcw&t=203s
[0] https://medium.com/@pinarkocak/mvc-mvp-and-mvvm-design-patte...
The point here is that you can write maintainable, clean, efficient JavaScript web apps without the load of complexity added by React.
No, Backbone.js doesn't do 2-way data binding, although some certainly made it do that. But it doesn't by default, it has a 1-way data binding (the UI updates when the model changes, but doesn't update the model automatically when the UI changes).
> Some people mistakenly think MVC implies 2-way data binding. It does not.
What? Who does that? I certainly didn't and I haven't heard anyone in my +decade of web development.
And that's only React, the ecosystem around it also has changed significantly.
https://web.archive.org/web/20130607112825/http://facebook.g...
Back in 2015, $JOB was evaluating upgrading Java 6 to Java 7 or 8. What is now? 20?
I last touched php in 2012, which was 5.4 or 5.5 I think. People were still arguing that Laravel couldn't replace CodeIgnitor, or that we should stick with Symphony or Zend.
Change is the only constant. In that respect, React has been relatively sane.
If you're a React developer, you'll have noticed that Javascript itself has changed a lot in ten years. The state management library your company uses has probably changed too. Compared to ten years ago, you're now writing fully-typed JS with Typescript. The additional libraries for authentication and persistence, and so on, have all changed as well. You may be using a graph-based database now. You may have a different JS runtime on the server. All of your tooling has probably changed, as has your IDE.
Whether React itself has or has not changed more than other frameworks, I can't say. But, I'd bet the stack used by the average front end developer has. Please recall that the original comment we're both talking about was referring to complaints about how much the front end has changed, with React only being the context of the comment, and not the sole cause of the complaint.
Ok then, what about the Spring .xml to .java migration? What about the Struts -> Struts2 -> SpringMVC -> SpringWebapp migrations.
It seems an unfair criticism of React.
When I started my first programming job 14 years ago xml was already not recommended and SpringMVC was already the way of doing things. So that's quite a bit stabler and slower than React.
And how much have you had to rewrite or replace going from 8 to 20? Very little, right?
But as practical tool, React has been a regression for the web IMO.
At the same time, my capabilities with web applications have skyrocketed in the last ten years and I wouldn’t credit it strictly to my experience. These tools aren’t only used because they’re relatively accessible; they’re genuinely capable and powerful, and when used well, allow remarkably fast development and iteration on products with real value.
I think that’s better than the bad parts. Also, a lot of what’s bad about the web today (for me at least) has virtually nothing to do with the tools we use to develop. It’s that our attention has been commoditized, and that market has eroded a vast portion of what made the web exciting.
If keeping track of state is so hard that requires a library to render it, perhaps you have too much state for a single view. It’s ultimately a UI/UX design problem, as it will be hard on your users as well.
I find the way they mix markup with code distasteful, and lots more.
Then you've never worked on a medium/large UI application (1k+ LOC), and most certainly couldn't have lived through the era of DOM manipulation!
jQuery when it first arrived was a god-send! but even the most thoughtful couldn't structure it right.
Backbone when it first arrived was a god-send! but even the most thoughtful couldn't structure it right.
React when it first arrived was a god-send! but even the most thoughtful still can't always structure it right.
With, the inclusion of so many other failed and semi-successful attempts throughout history I have no idea how you can possible claim:
> I don’t think direct DOM manipulation was ever a problem, if done thoughtfully.
without just being naive...
htmx is the first JS thing to tickle my curiosity in a long time. Vue seemed fun at first, but it got more complex than needed, IMO.
I agree, this is interesting. I even agree, htmx is probably a polyfill waiting for the browser standards to catch up.
That said, trying to make a markup language smart is a losing battle in the long-term. It makes simple things like `if` and `while` difficult. Markup also really struggles with time / interactivity.
e.g. What should be displayed when a form is invalid? https://htmx.org/docs/#validation-example is just not ergonomic even for a simple case, let alone complex validations that interact with other fields, are async, etc.
I get a allure of wanting "only a markup language", however, it just isn't enough to be competitive for 95% of web development these days. In a different response you say "if you're building the next Gmail, fine use React, but you don't need React for picking between 3 colors to order a shirt". This is true, but it is fundamentally lacking the realization that no company wants to end their feature set at 3 colors for a shirt. They "want" to build a foundation quickly, but then enhance it to be able to custom create the shirt for exactly your body sizes and allow interactive movement of the "logo" or "graphic" anywhere on the shirt. They want the validation to ensure the shirt can be printed, and they want to ensure their logistics network is dynamically updating the order history for live tracking of the package.
To get there, the best thing to do is to use React (or similar) even when it is "just 3 colors".
If/when you get a few million users, then you worry about scaling your backend with microservices, crazy DBs, serverless, whatever. Until then (vast majority of business), LAMP is fine.
If/when you need 20 checkboxes/drop-downs (again, there are very few situations where this is reasonable to the user, the mental load is non-trivial, consider splitting the view and adding a “next step” or something) than you consider a framework devised to render the whole of Facebook, a site with way more views and features than the most sites would ever dream of.
If you do however find the way markup and code is mixed feels distateful, I'd suggest to not look at any templating engine in the last 20 years because that's what most of them already did.
Regarding templating engines, I use PHP :)
Also, you don't need Virtual DOM to have declarative UI, just ask Svelte.
Compare that to literally hundreds of programming languages that can run server side code, dozens of database engines, servers, all kinds of operating systems, hosting platforms...the web of backend tech is pretty much endless, and growing every day.
The difference may be that once a particular back-end approach/architecture/design is adopted by a dev shop it remains stable over multiple projects. I’ve seen this in both consulting and in LOB roles. Because of this, I can hire a competent .NET developer and be confident that I can get them to be productive relatively quickly, since the foundation on which we write our code is stable, and I can invest in enhancing the developer experience to support them. In fact, an explicit criterion for every project in my teams is that we make it easy enough for any competent C# developer to ideally be able to open a small, but meaningful PR by the end of their first day on a project (if needed, I don’t treat it as a retention gate or anything!). They do have to adapt to our infrastructure and our ways of working, they don’t need to relearn the fundamentals of how to produce code.
Whereas every time a new front-end project starts, there’s a near-compulsion to use the latest and greatest techniques. Everyone has to catch up, because of their previous experience being somewhat redundant. No one can invest in improving things for other developers, because they don’t have the time, and because any investment would be wasted, since it would be redundant beyond the current project (or two, if we’re lucky).
I can’t really hire an Angular developer for a React project that starts tomorrow, and expect them to be reasonably productive immediately, despite them being competent in Typescript, CSS, Node etc. Heck, I wouldn’t even be able to hire a React developer who last did it 5 years ago, and expect them to be immediately productive.
It’s odd to me that frontend dev jobs ask for experience with specific frameworks, since most of the popular ones share core fundamentals a lot of the times. It’s no different than going to a new backend role to work on a large existing codebase. The codebase will have its own homegrown patterns and concepts to get familiar with anyway, how is this any different?
Edit: Is this the place to start? - https://react.dev/
From what I see from the tutorials...Why the closeness to NodeJS?
If starting a project, I'd probably start with Parcel.js [1] and from there use typescript/tsx instead of JS as a core. But that's just me. I also tend to do Redux the "hard way" closer to the original structure instead of redux-toolkit, as I find it's more overhead to learn initially but avoids a lot of additional complexity over time.
Can you clarify what your concerns are with RTK?
We specifically created it to simplify standard Redux usage patterns and eliminate common mistakes and bugs (like accidental mutations):
- https://redux.js.org/introduction/why-rtk-is-redux-today
We'd _like_ everyone who is writing any kind of Redux code to write that using Redux Toolkit, and we teach RTK as the default approach for using Redux. FWIW, we've had plenty of beginners tell us they were able to get started and be productive after reading through the "Essentials" tutorial in our docs, which walks folks through how to use RTK to build apps.
I'm not saying that RTK is necessarily bad, but feel that when you're using some of those kinds of slices, or merging the constraints of the actions, mutations and the abstractions, it's harder to reason with. You aren't thinking about state as a whole, or often even your fragment.
I'll sometimes mix a few things as well... The React features for provider/consumer, etc are sometimes easier to deal with as well. YMMV based on your own needs.
Per the docs examples (like https://redux.js.org/usage/migrating-to-modern-redux#reducer... ), hand-written reducers normally involved `switch` statements and lots of immutable updates with object spreads. Those were normally accompanied with a bunch of separate action type string constants and action creator functions.
With RTK and `createSlice`, the reducers themselves are much simpler: simple functions with "mutating" update syntax (which uses Immer to turn those into immutable updates), and the action creators get generated for free:
import { createSlice } from '@reduxjs/toolkit'
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
todoAdded(state, action) {
const { id, text } = action.payload
state.push({ id, text, completed: false })
},
todoToggled(state, action) {
const matchingTodo = state.todos.find(t => t.id === action.payload)
if (matchingTodo) {
matchingTodo.completed = !matchingTodo.completed
}
}
}
})
export const { todoAdded, todoToggled } = todosSlice.actions
export default todosSlice.reducer
That's a lot less code to write, much simpler and shorter to read, _and_ it eliminates accidental mutations.You're still writing a "slice reducer" at a time, so it's the exact same amount of state to consider (ie, a "posts reducer" that manages `rootState.posts`.
Also note that we do have a "Fundamentals" docs tutorial that teaches the underlying concepts _without_ any abstractions, but then shows how RTK simplifies those patterns:
- https://redux.js.org/tutorials/fundamentals/part-1-overview
Ultimately it's your codebase, but we really do _strongly_ want everyone working with Redux to write that code with RTK.
edit: I tend to find the separation of a more basic reducer, even with the switch, easier to deal with in practice. Not to mention, that action creators that are separate are easier to integrate with thunks and async data fetching IMO. The base library for Redux does very little. And if I'm going to stray from that, I'm more inclined to use something based on Proxies that feels more natural to use in practice than RTK.
I tried getting back to React but Vue makes so much more sense. Feels like in the old days because all you do is write your code instead of dealing with a library and its ways.
https://survey.stackoverflow.co/2022/#section-most-popular-t...
My bet for next-gen frontend tech is on svelte and SolidJS. They are faster, lighter and their tooling scene isn't as fragmented.
I do think the future of DOM based diffing is no longer going to use a Virtual DOM. Svelte has shown the way. It just has to be moved into React (or a React successor).
I also think the future of Components is to use async/await more. Where each await point is assigned a fallback component e.g. <Loading /> or something.
React also needs to figure out Hooks a bit better, and see if there is a missing language feature that can be pushed to simplify that concept.
If something (including React) is able to do those three things, while also keeping/improving the React DX (markup and logic together, uni-directional dataflow, hook like annotations that can interoperate with each other), it'll likely de-throne React.
<Suspense fallback={<LoadingSkeleton />}>
<MyComponent />
</Suspense>Where your Server Component then looks as follows:
async function MyComponent() {
const data = await db.get('...')
return ...
}There is a different type of delight that comes from the ergonomics on async/await. This is the big jump React Suspense also needs to make. I am not smart enough to suggest anything here tho. I just know the framework (including React) that can give me that async/await delight while using Suspense will dominate!
Other than that, prob. lit-dev (with time).
Yes. Nothing excites me more than web components and moving closer back to the browser. Somehow, it feels more exciting than server components, signals, compilers, resumability, etc. etc.