Live data from Hacker News

React I love you, but you're bringing me down

marmelab.com

521–530 of 574 posts

Re: React I love you, but you're bringing me down

#521

I must be the only person in the world who likes class components in React. Sure, it's often overkill and a functional component does the same thing with less code. Use a functional component in these cases. But if you're doing something more complicated then stop treating class components like the fucking devil. They have their place.

I ditched React soon after they released hooks, mainly because I couldn't relate to the tradeoff React roadmap was taking from there. They went in a different direction from that point onwards, it seem like whatever code you write will become obsolete with the new set of best practices in the next release cycle. More importantly, I realized React is trying to tame Facebook level of problems and hence their design dec…

Howard Lewis Ship kept changing the paradigm for Tapestry every major release or two. He could have had something to take the spot that Spring eventually filled, but these big gear shifts I think left people with a lot of rework and at some point it seems like porting your code to something more architecturally stable is a better bet.

It’s challenging though to keep supporting an API contract that you don’t believe in anymore. Or especially that you are causing you and others pain. I think sometimes maybe the thing to do is pass the baton and work on something else, but we also punish people for abandoning things. Like the author of Groovy, who hopped around from project to project and lost people.

Re: React I love you, but you're bringing me down

#522
post #16

Come to the dark side, we have cooookies https://github.com/cheatcode/joystick

I took a very brief look at your project. I saw reams of documentation, which is good, but not a single FAQ or a comparison table answering perhaps one of the most important questions to somebody who's already familiar with existing frameworks such as react, angular, and vue, which are: What distinguishes your framework? Who should use it? What does it do? And more importantly, what doesn't it do?

> but not a single FAQ or a comparison table

This is on my list for the 1.0 release. Unofficially...

Edit: You motivated me to rough something out, take a look here: https://tinyurl.com/joystick-comparison

> What distinguishes your framework?

Simplicity and stability, primarily, and second: scope.

The current crop of frameworks seeks to overcomplicate APIs and are indecisive about how things should be done (as evidenced by the introduction of patterns that are "the way" one day and then a few months later are "deprecated"). This leads to a lot of confusion at the community level which makes it hard to build software that can endure overtime (I came to this conclusion through teaching developers and realizing how much time was wasted chasing the proverbial rabbit of indecision).

Even worse, these frameworks introduce their own languages/syntax which are foreign to what a beginner would learn (HTML, CSS, and JavaScript). This not only creates confusion and slows down the learning process, but it also creates the long-term nightmare of developers not understanding the fundamentals of the tools they use to build. Eventually, you hit a drop-off point where people think that, for example, JSX is HTML and in a pinch where they can't use React, are ineffective or incapable of completing the task properly.

By contrast, Joystick is designed to be stable, long-term, from the beginning (i.e., no random "hey, we're deprecating all this stuff you depend on for this more confusing API that's less descriptive"). It's also based on the core technologies of the web: HTML, CSS, and JavaScript. I don't introduce any hacks or sytnax tricks to render the component. It's plain HTML, CSS, and JavaScript. This means that the transition from learning the basics of the web to shipping apps is far smoother (and an individual developer is less likely to make mistakes/get confused as everything looks consistent with where they started).

I also intentionally designed the component API to be fixed long-term. So, a component you write in Joystick today will look the same 10 years from now. My focus will be behind the scenes, improving performance and security. This matters less to developers and more to businesses (my target) as a lot of time and money is wasted on developers who are more focused on tinkering with technology (and making messes) than actually building the thing they're supposed to build.

For scope: Joystick is a full-stack framework, not front-end only. The UI part (@joystick.js/ui) is designed to snap in to the back-end/server part (@joystick.js/node). The advantage is that you're not wasting time trying to stitch together disparate parts that may or may not work together (or even worse, may or may not be supported long-term).

> Who should use it?

SMBs, startups, and freelancers/contractors. For SMBs/startups, it's a solid framework for shipping custom software for your business (or a consumer/b2b SaaS) that you can rely on long-term. So, build it today and maintenance is limited to some patch upgrades and new features/improving existing features. Never a surprise refactor being plopped on the roadmap, distracting you and your team from delivering value to customers.

For freelancers/contractors, remove the overwhelm of juggling a bunch of disparate codebases across clients that each have their own shifting requirements (i.e., standardize what you ship, full-stack). This allows you to take on more work, but also, make your long-term support more predictable as the framework you're building on isn't going to rug pull you down the road. This allows you to build a better business with happier clients.

> What does it do? And more importantly, what doesn't it do?

It allows you to define routes on the server which when matched, render some HTML, CSS, and JavaScript using a component framework that's a light abstraction over those core technologies. It also makes it easy to define a JSON-RPC API that can be called directly from components, giving you complete transparency into the flow of data between the client and server without any ambiguity. In addition, it adds the necessary wiring to start and connect drivers for databases to your app, piping those drivers to where you need them (namely, your routes and your API endpoints/handlers).

The back-end is just a plain Express.js/Node.js app so anything you can do in a standalone Node project, you can do in Joystick without any limitations. So, if you want to use a third-party package, just run npm install and it will work.

All of this is backed by a built-in SSR/hydration implementation so all you have to do is write your routes, API, and components. No time wasted on wiring the front to the back-end. All of that is automated via the lightning-fast build system built around esbuild (which is implemented/configured out-of-the-box) so you can just run `joystick start` and get to work in a few seconds.

Thought it sounds obnoxious, what Joystick doesn't do is get in your way and it isn't a ticking time bomb of deprecation. It allows you to actually focus on the product you're building, long-term.

Re: React I love you, but you're bringing me down

#523

I must be the only person in the world who likes class components in React. Sure, it's often overkill and a functional component does the same thing with less code. Use a functional component in these cases. But if you're doing something more complicated then stop treating class components like the fucking devil. They have their place.

I totally agree. I just joined a shop that has banned new class components from entering the codebase and I still don't understand why.

Re: React I love you, but you're bringing me down

#524

Earlier quoted context omitted.

Yes, there is something very weird indeed. Functional components are called every time they're rendered (that's not weird). But they have to maintain state between calls; they can't start over again fresh for each call/render (still not weird). So how do they do this? `const [state, setState] = useState(initialValue)`. You might look at that and think, I see useState being called, so it must be called on each render,…

That is bonkers, to be honest. I've used React a lot, but only via Reagent in ClojureScript. I think the JS people are being scammed.

It sounds bonkers, but one of the reasons I pushed for moving my company’s app to React was because the useState hook reminded me of Reagent’s ratoms. I believe that was at least part of their intent. The catch is that you can’t really enforce immutability or atomic updates in plain JS, so they built hooks into the library as a workaround.

There’s not much of a cognitive difference between “defining a reagent component which uses ratoms and calls a pure function that derefs, updates or swaps them”, and “defining a react functional component that uses hooks”. It looks weird to have the “atoms” inside the render function instead of outside, and there are the aforementioned limitations (“the rules of hooks”), but it’s a compromise to get the feature into JS React in a consistent, performant manner.

I’d love to use CLJS/Reagent or even go full re-frame on our front-end codebase, but that’s a hard sell at my company since I’m the only dev who’s ever played with Clojure.

Re: React I love you, but you're bringing me down

#525

Earlier quoted context omitted.

Hooks had nothing to do with v8 optimizations or `this.state`. Per https://reactjs.org/docs/hooks-intro.html , the primary motivations were: - "It’s hard to reuse stateful logic between components " - "Complex components become hard to understand" - "Classes confuse both people and machines" (remembering how `this` works, code minification, method binding, etc) There's also an excellent "Why React Hooks?" post at htt…

> This works because closures capture data in a scope, whereas mutable class instances could have gotten changed and refer to a single `this` instance. So `this.state` is hard to optimize? > Hooks had nothing to do with v8 optimizations or `this.state`. Huh? That's what you just said. The spec makes it hard to optimize. The JIT compiler can't infer enough about the shape of the data.

You're very much misreading what I said.

It's not about "optimization" in the sense of "how fast can the v8 interpreter execute lookups on the class instance" or anything like that.

It's about "when this function executes, what data does it see, and did any of those values get changed out from under it in a way that could potentially break the logic"?

Re: React I love you, but you're bringing me down

#526
post #366

Earlier quoted context omitted.

Not sure what you mean by "nightmare" - can you clarify?

* The risk of thrashing seemed very high * Debugging performance issues seemed like they were going to be a nightmare. Worse than right now. Worse than hook hell.

I think you're really misunderstanding how React works here.

There's no "thrashing" involved, in the sense of "make DOM update A, then need to make B that reads layout or does reflows right after".

- React does a render pass based on a state update, compares the element tree from this render vs the last render, and determines _all_ the necessary changes to make the DOM match the newly requested UI

- It then applies all those changes together, synchronously, in a generally efficient way (ie, modifying just specific attributes to existing DOM nodes if possible, vs recreating the DOM from scratch)

Which "performance issues" are you thinking of? Excess renders? DOM-specific reflows?

Re: React I love you, but you're bringing me down

#527

I know it's not the point, but you can generalize the input handler in the first example by using the name of the input field as a key — in most simple forms, at least: ``` const Form = () => { const [formData, setFormData] = useState({ firstName: '', lastName: '' }); function handleChange(event) { const { target } = event; const { name, value } = target; // Destructuring in steps to make it easier to figure out wher…

even better, wrap those props as

    
and make a custom hook returning that getProps function

Re: React I love you, but you're bringing me down

#528

Useless rerenders are really hard to avoid in the latest react, mostly because they changed the rerendering logic of useTransition, breaking some of the state abstractions built on top of it. Had to downgrade and started to think about using class-based components again. Hooks are very beautiful but too weird, weak and leaky as an abstraction, unfortunately

I don't think you especially need to try to prevent useless re-renders, as long as it doesn't slow down the app

Re: React I love you, but you're bringing me down

#529
I doubt web devs would ever accept React as the de facto JavaScript framework and we definitely shouldn’t if it wants to keep evolving but most of the articles against react these days seem to be the equivalent of frat boys negging and mocking woman just because it’s the cool thing to do.

I’m sure there are some good points being made out there but those points Are getting lost in the noise which is a real shame.

Re: React I love you, but you're bringing me down

#530

Earlier quoted context omitted.

> Some part of your organizations chaos is going to reflect in code, and honestly I'd rather it be in a big ball of frontend than in the data models, infrastructure, etc. I disagree. I like my frontend to be as dumb as possible. It gets data and reacts to it as simple as possible. Seen too many frontends with a lot of data logic and it becomes extremely brittle, harder to test. These are the ones where the frontend d…

That's why I like GraphQL, you get exactly the data you request, no transformation necessary.

Graphql does not address the problem he's describing. When he says "transformation" his meaning is similar to transformation in an ETL process. What he means is the application loads data, the user takes an action, and the front end code handles updating the objects locally, then sends messages to the backend telling it what the new data state should be.

This is very dangerous behavior for any application. You don't want the front end to determine how much the shopping cart costs or to just tell the backend they've paid, therefore add the items to the orders list. Even if there isn't blatantly obvious security concerns, you should still never let your front end blindly determine data state changes. All such business logic belongs in the backend as much as possible.

What he's talking about is when business logic is split between the front and backend, which makes everything much harder to test on top of increasing the likelihood of duplicate code or even code which does the same thing but looks different enough to not be caught as duplication (which means changing business logic requires finding all the places it was implemented and changing them all, and if you miss any its unlikely anyone else will realize it until it hits prod).

The UI should always just be a shell that sends requests to a backend which determines which updates to make. There are exceptions like when a user makes form based changes to an object, but the only business logic in that case is "let the user decide what the value should be and persist that choice as is". If any additional changes may need to occur as a result of their change, your backend should make them. Even if you just need to determine if a change shouldn't be allowed because of related data, send a request to your backend requesting the answer and any relevant data necessary for display purposes, not the data necessary to make that determination.

There are exceptions to what I've said, but even in those cases, the backend should still verify whether the front end's result is correct. While the front end was working, a change could have gone through in the backend which invalidates that change. This is why things like concurrency/version tokens can be very important.

In any case, Graphql may have capabilities that look like they help keep business logic in the backend, but it doesn't stop programmers from putting business logic in the front end anyway. No matter how you try to look at it, spreading business logic out across your applications various layers always has unintended consequences for maintainability and even scalability.

Post reply on HN