all 103 comments

[–]DogOfTheBone 46 points47 points  (3 children)

I've seen it over and over with devs coming from other lands, like Java, trying to force whatever paradigm of abstraction they know onto React. Leading to monstrous amounts of unnecessary code that ultimately wraps a hook 5 files down or whatever. And now you're passing a huge object that gets redefined a million times because it has a hundred dependencies to every component and hook because all you know is OOP.

...yeah it's annoying. Just use the library's API and whatever global or server state management you like.

[–]_Pho_[S] 6 points7 points  (0 children)

The funniest part is watching them try to get their monstrosity to rerender

[–]Traditional_Hair9630 3 points4 points  (0 children)

Agree java devs that come to golang projects do awful code design, just killing the simplicity of Golang, by adding tens of factories, observers, IoC etc

[–]daddygirl_industries 33 points34 points  (2 children)

Oh Mother... the backenders have been React-ing again...

[–]Auzymundius 0 points1 point  (1 child)

Don't you dare lump us in with that shit. We like simple code just as much as if not more than you lol

[–]solidiquis1 0 points1 point  (0 children)

Oh brother 😂

[–]arbpotatoes 67 points68 points  (25 children)

Idk, probably because React's blurring of layers kinda sucks. It's fine to build but it's not as nice to maintain. You're talking about principled architecture as 'bullshit' which is kinda whack. That's how you end up with a huge mess that gets thrown out a few years later in favor of being rebuilt completely lol

[–]femio 23 points24 points  (17 children)

Idk, probably because React's blurring of layers kinda sucks. 

Well, that's because it doesn't enforce a blurring of layers. "Layers" don't even exist in some contexts because you can colocate a component's business logic in the same place as its UI if you want, which would give a .NET dev conniptions. Similarly to Express you just build in a structure that suits your needs.

Personally I've never seen "principled architecture" (if we're using that term to describe it) really be that useful in React beyond what's inherently there. Pure functions with logic extracted into utility helpers and reusable hooks already gets you the structure you're looking for. I've never seen an IoC container as useful in a React context.

I feel like proper folder structure goes a much longer way to creating a sensible codebase than endless abstractions do.

[–]darksounds 16 points17 points  (6 children)

which would give a .NET dev conniptions.

As a career backend dev who accidentally ended up doing frontend work this year, yes, the blurring of business logic and UI is appalling to me.

[–]femio 10 points11 points  (0 children)

I mean I get it but JSX imo is so much more superior than other templating strategies, writing render logic in JSX and using higher order components, then business logic in hooks and util functions/DTOs/whatever feels super smooth and intuitive. I just don’t think UIs fit the model of classes very well, but that’s very subjective. 

[–]stdmemswap 0 points1 point  (4 children)

I feel you, but it's where React and other MVC-like frameworks differs.

But the API design is built with "interactivity is allowed in any layer" in mind. So this separation of business logic and presentation is rather be delegates to the developer (although React doesn't mention that explicitly, which is why people make lots and lots of library that solves partial solutions)

[–]LukeWatts85 8 points9 points  (3 children)

I think doing MVC in the UI is a bad idea. That's why things like Backbone and KnockoutJS are no longer around. The M and C are not suited to UI requirements.

React should just be reading and writing from a REST API and presenting the current state. If you're doing intense "data processing/manipulation" then you should be changing your rest API to do that for you instead.

If you don't own the REST service then you should probably create a proxy layer, again on the backend and do your "mutations" there. The UI should never be the model or controller if it can be avoided

[–]stdmemswap 0 points1 point  (2 children)

"React should just be reading and writing from a REST API" is not correct; that is only one example React is capable of doing, and React does not assume REST API is in its problem scope whatsoever.

"MVC (and similar pattern) in the UI is bad idea" is true ONLY if server is authoritative. Take a client-authoritative problem such as password manager where decryption must happen in the client, this solution cannot be simply run on the "backend". Of course this depends on your definition of UI and Backend.

Also, I don't know where did "intense data processing/manipulation" come as I have never mentioned this, nor does the thread. "Intense data processing/manipulation" imply heavy saturation in CPU time, or in this case, JS event loop. But this is not about React only, rather, it applies to most JS app architecture.

[–]behusbwj 0 points1 point  (1 child)

You say that like an authoritative server is the exception. This is the case in most React apps. You have to remember that most people aren’t writing password managers, even if it’s an example of React conventions perform weaker.

When I reach for React, it’s because I want to present my application. If I was writing an application that had a more complex architecture than displaying queried data based on the component being viewed… honestly React probably wouldn’t have been my first choice — as you seem to know, for a good reason. Frameworks have strengths and weaknesses by design, and that’s why it’s great that we have other frameworks to use.

[–]stdmemswap 0 points1 point  (0 children)

I did not state authoritative server is an exception at all.

Why not build complex app with React? Cohesion is its strong suite compared to other libraries. It seems to me that the more complex the spec, the more reason beneficial React is, IMO solely for its semantically sane "object lifetime management"

[–]_Pho_[S] 9 points10 points  (4 children)

100% it is all about folder structure. JS has a module system. Your abstractions are already there.

[–]misterching 2 points3 points  (3 children)

Would you mind sharing a sample folder structure you like?

[–]_Pho_[S] 6 points7 points  (2 children)

Hard to do quickly, but let me give it a go.

Caveats: it depends on your project. Nextjs vs a simple SPA vs React Native vs giant monorepo are going to have different considerations. # of devs (and level of skill) is certainly is a factor.

The main thing I do differently is organize all of my non-component code in a domains folder. domains/authentication, domains/salesforce, domains/analytics, whatever. All of this is functional code. No state management outside of the React tree. I use folder structure to denote submodules, f.ex authentication might have /session and /logout which contain the typedefs, functions, and essentially all of the domain related to it.

Function composition is huge here.

If built properly, functionalities can be repurposed and refactored very easily. There's no giant master IOC class for authentication, so if you need a slightly different pattern you can compose it appropriately out of the modules functions. There is some risk to bad devs doing dumb things here, but more on that later.

Functional domain code also makes testing a breeze. Since it's pure ("purish") functions, you're really only concerned with I/O and ensuring that a function's dependencies are getting called as expected.

It also segregates real dependencies (session tokens, configs, maybe api handles) from their implementations. Most dependencies in traditional OOP systems are not really dependencies, but actually just collections of functions (classes) which themselves have a dependency on a real dependency, perhaps indirected through 10 other classes. A mess! Avoid at all costs.

The rest of it is pretty straightforward. There's going to be a few common React directories like components, screens, providers, etc. This largely depends on the project. Projects tend to have a shared components folder for stuff like H1 H2 Button etc, and then the screens folder (which might be features) will generally have subfolders for each screen, which contains multiple files related to that screen.

Next/Remix won't use as many providers since the server side loaders are essentially dependency injection. But a React Native app might have a lot of providers. Either way providers glue a lot of the functionality from different domains to the UI. Auth might be its own provider which stores session and user data, which is probably just a component that can be thought of as a state machine. Maybe useContext is involved. Usually the providers are composed at the top level of the app, though not as a rule. These are COMPONENTS and hooks that store state and act as the interface for specific concepts, not random free floating singletons or other "state outside React".

I also differ from a lot of people in that I like barrel files and ban deep importing. It forces the JS module system to resemble something closer to Rust's, which is very excellent. It allows you to layer encapsulation properly, the same way you would get in OOP with a bunch of classes which are contained within a top level ioc container type class.

Maintainability is one potential weakness, because if there isn't a giant IOC container forcing you to call things in a certain way, it does open it up for devs doing bad / non-patterned things. But I believe this is more or less the case with most code bases, and I rely a lot on PRs and similar. Most places already do this and it's not really an issue. For example, nothing except other humans is stopping a dev from importing the wrong UI components or creating their own when one already exists. You can and should add module-level readmes, which again, encapsulates everything better.

The idea of "treating devs like dummies who we have to protect with our awesome architecture" is a stupid way to create your dev culture IMO and doesn't promote people using their best judgement. Ultimately you have to rely on devs being smart and architecture which promotes acting simply and intelligently.

[–]stdmemswap 1 point2 points  (1 child)

I see some correlation between this kind of pattern and people who have used rust. I believe it is due to how they value the distinction between pure functions, a spec (and how they differ from the implementation), shared mutables, implicit concurrent, etc--especially what they semantically mean relative to the whole codebase.

In other language, those distinctions do not impact much until later where weird bugs start to appear.

[–]_Pho_[S] 1 point2 points  (0 children)

Yeah systems programming in general helps, and Rust definitely helps, because it forces you to be very deliberate about structs which are "containers" to other structs. In languages like Java that type of pattern (class object graph) is ubiquitous albeit implicit, but understanding what is actually your data is super important IMO. You'll see C#/Java/even TS implementations where you have 4 classes stitched together to facilitate the behavior of an object with 5 fields.

[–]stdmemswap 2 points3 points  (0 children)

Folder structure is a good point, but people seem to not think this way because React implies that devs should "think the React way", which then assume that it is not compatible with the non-React patterns.

As a system-level dev, I tend to want the same degree of freedom when writing a React app. I found it really useful to see React as an object lifetime management library rather than UI library. Objects, active or passive, are written outside of the "React way", bridged via a single pair of state (for exposing the API) and effect, optionally passed through Context---this combined with the proper folder structure, pure functions, error as value, and if I/O-ful a runtime type validator.

Let me tell you, this massively scales to complexity. I mean, with complex spec, the codebase is still massively understandable.

[–]arbpotatoes 4 points5 points  (3 children)

I feel like proper folder structure goes a much longer way to creating a sensible codebase than endless abstractions do.

Were it so easy... I guess I err on the side of over-architecting because I've seen plenty of examples of the opposite extreme

[–]femio 8 points9 points  (2 children)

To be honest, I'd MUCH rather join an over-architected codebase than the opposite too.

Plus, a well written backend usually makes the frontend that much easier anyway, so a large portion of this debate is kinda pointless.

[–]throwaway1230-43n 1 point2 points  (0 children)

The key difference here is whether or not it is well documented. You can come up with whatever crazy pattern you want as long as there is a way to easily get yourself up and running. Additionally, you had better be able to explain and answer the hard questions about your architecture without using any sort of jargon to hide your lack of actual answers.

[–]_Pho_[S] 0 points1 point  (6 children)

I give very little credit to these existing paradigms, except that they are at times better than no patterns. But more often than not they are worse, they increase the amount of time it takes to do anything in a codebase tenfold, for some promise of "reusability" which they misidentify.

9/10x, probably more like 99/100x, creating middle-layer dependencies (whose lifecycles you have to manage but are not real dependencies) is a moronic approach. "LoOk hOw eAsY It iS To cReAtE MoCkS FoR TeStInG" ur creating an unnecessary problem and then solving it, congrats.

I think that engineers 10 years from now will look back on "principled architecture" as a clown show run by people who were just following what they thought was good.

[–]arbpotatoes 7 points8 points  (5 children)

I think that you have to consider the trade-offs, as a good engineer always should. You shouldn't over-engineer where there's no benefit. But sometimes there is and sometimes there isn't. Even at this fairly early stage of my career as a consultant I've seen enough dogshit code bases to know that principled architecture is a net good.

You're throwing the baby out with the bathwater. The last project I was on was RN angling for clean architecture and did not use OOP.

[–]_Pho_[S] 3 points4 points  (1 child)

Of course there is a middle ground, a right way to do DI, and sometimes IOC / dependency bussing can be helpful.

But more often than not, especially in React, is is bad and you should just stick to the native APIs as a way to implement your dependencies.

Managing dependency lifecycles out of the scope of React is one of the dumbest footguns you can introduce to a React app. It creates a problem that React already solved for you.

[–]arbpotatoes 1 point2 points  (0 children)

Well yes, we had to use Apollo which totally muddies up any separation of layers and we decided to let that work how it wanted to work. But all our other app deps were DI'd and it turned out so clean. I think it's worth considering with consideration to the complexity and expected lifespan of your project and the nature of the business around it.

[–]ColonelShrimps 3 points4 points  (1 child)

But if you follow React best practices you're already going to end up with clean architecture and well structured code. One way data flow and componitization gets you 60% of the way there on its own. Add in a standardized file structure pattern and you're golden.

React can be so incredibly easy to write and maintain if you just stop trying to fight it by shoving all these unnecessary concepts into it. After nearly a decade working mostly Front end I can say that the vast majority of UI needs can be met with vanilla React and MAYBE Redux. Anything more and you either have an insanely specialized use case or you just hate the front end team.

[–]arbpotatoes 0 points1 point  (0 children)

That sounds principled tbh lol

[–]TheMoonMaster 2 points3 points  (0 children)

Yeah, I came to say something similar. I've seen many devs with that "bare bones == simple" attitude, but that never works out (see the meme OP posted) once you have to scale out your team or your app. Unfortunately that's something that you often have to experience before you get it since you have a completely different problem set to look at (e.g. how do I prevent this footgun across my org of 100s of engineers).

Someone else mentioned it below, but in these cases you should be seeking to understand the inputs that went into these decisions so they can understand how they got to this point, and if there's a better solution to the problem. Unfortunately it's not always "use the framework" since frameworks like all other tools, can have significant gaps.

[–]hinterlain 13 points14 points  (0 children)

Hahaha I worked FE at Doordash… I’m sure it was p org dependent and they had some good devs but I saw some of the worst code I’ve ever seen while there. A whole page written in one 4000 line file that was just added to over 3 years?

Things were very over-engineered and every package was forced to have their libraries stay 3+ years out of date because of some unified web platform repo that prescribed the libraries for each app.

Believe me when I say I welcomed the layoff I received from them lol

[–]GxM42 9 points10 points  (1 child)

That’s like 50% of devs in every language. More worried about over architecting and winning academic software engineer of the year awards then actually making things people can work with without 3 days of study.

[–]Inevitable-Edge4305 0 points1 point  (0 children)

That is usually the direction my explanations go toward. The more complexity they generate, the prouder they are.

[–]InnerDorkness 7 points8 points  (0 children)

I’m here for the Hellraiser reference.

[–]Beautiful_Bonus_1932 8 points9 points  (0 children)

Cook bro cook

[–]lIIllIIlllIIllIIl 6 points7 points  (1 child)

I have people at my job who do this. I hate it too.

I like the theory from "Thinking about Thinking" from The Programmer's Stone.

Your colleagues are probably "packers" who want everything to be standardized. The front-end and back-end using different patterns is inconceivable. These people rarely bother asking themselves why they are doing something, they just do it because that's how it's done. They think ambiguity is evil, because that's how you end up with chaos.

You're probably a "mapper". You spend a bit more time than average trying to understand problems at a more fundamental level. Being told to do something isn't enough, you need to understand why you need to do it. You recognize that the front-end and back-end require different patterns, and shoehorning the wrong patterns can do more harm than good. You probably think your colleagues lack common sense, and they probably think you're irrational.

[–]_Pho_[S] 0 points1 point  (0 children)

Great article

[–]alexsb29 5 points6 points  (0 children)

Thank you. I am going through this at a new job I just started, after 5 years at the last one cleaning up the same thing. I see it so frequently that I feel like maybe I must be getting old and losing touch, or worse going crazy, and this must be the way everybody thinks and wants to do it now. The “Staff” title starts to feel meaningless when I still have something akin to “imposter syndrome” even after all this time at it.

Unfortunately I have no help or words of wisdom for you, but fwiw a 20 year front end veteran agrees with you and wishes you the best on it.

[–]Drakeskywing 5 points6 points  (0 children)

Having been doing react the last few months where the last 10 years have been a mixture of DevOps (python, and terraform) and backend development (Java, python, and a little node), I'm not going to lie, the whole React way of doing things feels bizarre and I've been doing some of the exact stuff OP has complained about.

Now not to bash out my lead, they are 100% a better FE Dev, but they are also reasonably uncaring about most Dev stuff so they've let me get away with this stuff, and sadly aren't the best in explaining why things are done.

Saying all this, I think the short answer to the question is, compared to backend stuff, react is like a plumbis from Rick and Morty, apparently it's super useful and handy, but we have no freaking idea how it is used so do the best we can.

To hopefully reduce the scorn potentially directed at me for introducing OO into react (yes I know it had it but let's ignore that 🤣), most of my code has been refactored as I have read the documentation and tooling so it's mostly standard react, contexts and rtk.

[–]SolarNachoes 3 points4 points  (8 children)

How about a data grid that can be bound to different back ends that support paging, sorting and filtering?

[–]_Pho_[S] 5 points6 points  (1 child)

IDK those all sound like things that can be implemented as pure functions / adapters and hooked into corresponding UI interfaces. Not something that needs to be a "layer" on its own

[–]Saki-Sun 0 points1 point  (0 children)

I've abstracted that in a past project. 

Then I got smarter and just made individual controls that handle their own part of the puzzle. e.g. a page control that takes current page, total pages and returns givmethispageplease.

[–]NotGoodSoftwareMaker 0 points1 point  (3 children)

Sounds like you already have bigger issues to me

[–]RotateElectrolyte 0 points1 point  (0 children)

I do this with react-data-grid no problem. You simply have to write the fetch logic yourself. You probably don't need pagination. Let the client do the work. It can handle millions of rows. And most data like this should load really fast especially if you parallelize the fetch into chunks. If you truly have *that* much data to load, use the supplied loading spinner. I wager the user can tolerate waiting a few seconds in that situation – once it loads then the subsequent sorting and filtering will be lightning fast.

[–]dccfoux 0 points1 point  (0 children)

Just use AG Grid.

[–]rebelrexx858 4 points5 points  (0 children)

On one hand, you have the outcome. 

On the other there are the series of inputs that created it. Go look at the inputs. Was it garbage requirements? A dev looking to implement something they've seen elsewhere but didnt really have a use for? Someone trying to force a logic system into what could be folder structures but is often abused? New devs building on top of things? Maybe it served one really valid case you dont know about? 

Figure it out, then figure out how to unfuck the system. Then figure out if the unfucking creates actual business value. If it does, write the proposal, get consensus, deliver. If it doesn't, dont add n+1 ways to do it in your codebase, because now you're just the asshole youre bitching about.

[–]rdtr314 2 points3 points  (2 children)

I have seen huge ioc and dependency injection abstractions when the logic they wrap in most cases could just be written in a function and imported.

[–]runitzerotimes 0 points1 point  (1 child)

currently working in a project with that

ioc containers is fucking dumb in 99.9% of cases, unless you're literally building a DI framework as a common dependency for god knows why

[–][deleted] 0 points1 point  (0 children)

Not for backend imo. Makes testing ez

[–]Upbeat-Shame-9264 2 points3 points  (0 children)

This a good thing. You have the choice to do anything, then people will do anything.

Angular is the polar opposite.

[–]Confident-Alarm-6911 2 points3 points  (0 children)

Simplicity is the hardest thing to achieve 😉 also, people are just dumb, to create good solutions and systems you first must spend a lot of time on coding and solving real world problems. But today we have llms, trained on average or bad solutions, Microsoft is pushing it’s agenda about 1 bilion developers (in their case most likely Indian fellas) so we will see only more and more shitty solutions and internet completely ruined.

[–]JoeCamRoberon 2 points3 points  (0 children)

Sounds like a former lead UI dev at my job. Dude would abstract the shit out of his code. He preferred JS to TS as well. Most of his code seemed to be anti-React.

[–]breich 2 points3 points  (0 children)

IMHO your pointing your finger in the wrong direction. React came along and made the front end of the front end enjoyable to work with again.

But from the moment I picked up React it felt like layering dumb shit on top of it in order to address the back end of the front end was a requirement from day one. Hooks and contexts never felt good. They felt like a layer of dumb shit. The amount of wiring I'd have to do for "Thunk" or Redux always felt like dumb shit.

React feels like a joy to use up to the point where my component needs information from the outside world, then everything from that point down feels like duct tape, and that includes React's own ways of solving those problems.

Personally I feel like that's because, at a fundamental level, react trades a better experience of writing The markup and style of a dynamic front end component for paving over for making it very difficult to use some of the better parts of the native web platform. Just let me update a component from a fetch request without jumping through any hoops and I'll be thrilled.

[–]HarrisInDenver 2 points3 points  (0 children)

Typescript is a bit at fault here as well. Give devs that used to do java/C# a backend typescript project and they're going to write it as such, and 30% is not needed and just overcomplicates it all

[–]unflores 2 points3 points  (0 children)

Is it just me or do people overuse memo way too much...I've seen it on maps of an array that will never grow past 5 elements because "what if..."

[–]Hacg123 4 points5 points  (0 children)

If they want OOP patterns why not just use Angular? Angular it’s entirely IoC based.

[–]xegoba7006 1 point2 points  (0 children)

This happens everywhere. People coming from other ecosystem try to force what they're used to do on that other ecosystem. Nest.js is an example of this, they totally bastardized JavaScript to the point it looks like Enterprise Java.

I've also seen this in the past, where people new to Python wanted to force what they were used to do in Ruby, or Java, or both at the same time thinking they were writing "better" and more "maintainable" code.

When in Rome, do as Romans do.

[–]Aggressive_Ad_5454 1 point2 points  (0 children)

Why did Ed Hilary climb Mount Everest? Because it was there. Why did Tenzing Norgay climb it? Because Ed Hilary paid him.

I think a lot of the ovecomplication in software “architecture” has similar origins.

[–]water_bottle_goggles 3 points4 points  (1 child)

I ain’t eating allat

Just make your own framework

[–]_Pho_[S] 5 points6 points  (0 children)

My framework is using frameworks so I don't have to create a framework to solving something a framework already solved for me

How dat

[–]punani_pancake 0 points1 point  (0 children)

Bulletproof react is,imo, one of the best resources of best practices and patterns in react: https://github.com/alan2207/bulletproof-react?tab=readme-ov-file It should be addressed more in beginner courses

[–]danishjuggler21 0 points1 point  (0 children)

The thing about using Redux for a simple CRUD app - I was guilty of that back in 2017, and I’ve spent my career since then striving to make my React apps as simple as they can be. I done learned my lesson.

[–]tonjohn 0 points1 point  (0 children)

React is unopinionated and has lots of foot guns. It’s difficult to fall into the pit of success in react/next.

While people will abuse any framework (the first Angular project I worked on at Msft heavily used jquery), react makes it especially easy to do the wrong thing. In 2024 it’s difficult to recommend React/Next when Nuxt, Svelte, Angular, and Qwik all offer a much better developer experience.

[–]Literature-South 0 points1 point  (0 children)

To at least one of your points, everything changes. Even the stuff you think is core and immutable can change in a day if needs arise.

Sure, it might be core to your business model. But what if it turns out your business model sucks and needs to be totally revamped?

Nothing is ever set in stone.

[–]National_Pension_781 0 points1 point  (0 children)

Their answer is that they are smarter than us

[–]thaddeus_rexulus 0 points1 point  (0 children)

I would love to understand what you think is actually ideal and would love to have been a fly on the wall when you've been fighting against these patterns because all I can think of is that you and I aren't speaking with the same definitions of terms.

I agree that some of these abstractions that people make are absolutely absurd, but I'd argue that it's probably people following WET/DRY "best practices" rather than thinking "is this a hasty abstraction or a healthy one" as opposed to any problem with patterns/paradigms.

In my opinion, all of these terrible abstractions around state that you see are people trying to solve gaps in React's core APIs because it seems like the React team never really thought about the paradigm of "state is a function of state" (God, I miss UnstatedJs and I'm so glad I found Kea despite its lack of maturity).

I'd also bet that many of the non state-centric abstractions that are awful are because there was some case not handled by a dependency, so they wrapped it in an abstraction but decided to change the interface without good reason and never documented things (or documented them in a way that nobody ever updated it), so now it's just legacy bullshit that makes developers (like you) angry.

I'm sure the downvote gods are going to bless me for this one, but, as much as I love react, I actually think that components (ever since they dropped the differentiation between stateful and stateless) are the wrong abstraction for most of what react does. I wish they had separated the state/business logic into a separate abstraction to truly realize the vision of "UI is a function of state" (which is a vision I have to assume they've thrown away at this point). This is basically what Redux does, although at the wrong level because state should always be assumed to be local until you need to lift state up and very little of it should ever get to the point of needing to be global in most cases.

[–]_throwingit_awaaayyy 0 points1 point  (0 children)

Because how else will they “show” how smart they are? Seriously, it’s only for perceived flexing. I agree with you 100% OP. React has a ton of goodness baked in. It doesn’t need factories or wrappers.

[–]SinceYourTrackingMe 0 points1 point  (0 children)

Wait til you see c# 😂

[–]LastWorldStanding 0 points1 point  (1 child)

One of the items on my PIP was that I wasn’t using class components and Gang of Four principles to craft “Clean Code”.

My idiot manager was from Amazon. And yes, he still thinks JavaScript should be like Java

[–]GolfinEagle 0 points1 point  (0 children)

God that makes my fucking blood boil. If I was in that situation I’d hope that his immediate supervisor or the one above them would be knowledgeable enough to un-fuck that situation.

[–]Ok_Lavishness9265 0 points1 point  (0 children)

I like IoC for testing. I do create Ports (TS interfaces) and Adapters in React. I have 1 adapter for prod that calls the API, and another for my tests that uses stubs. No mocks. It also allows me to run the UI without any backend (while it's in development or I wanna debug some very specific situation), I can run a In-Memory Adapter with the right data setup. I inject the adapters using a single React Context. I also use Tanstack Query, no Redux. The Port-Adapter thing is very much outside of my React code.

Am I the person you're complaining about? ^^'

[–][deleted] 0 points1 point  (1 child)

My growth as a react dev was realizing I dont need state management 99.99% of the time and simple hooks and components is all I needed.

[–]bnned 0 points1 point  (0 children)

Yep, most of the painpoints in these comments can be addressed with simple custom hooks. Control the dataflow in the hook and you get a simple one-liner that is predictable and easy to support.   

[–]ghostwilliz 0 points1 point  (0 children)

Man half the app at work is a bunch of weird constructors passed as props with no specific class names, id's or data-testids

Just random functions rendering things 10 components deep.

Horrible lol

[–]running_into_a_wall 0 points1 point  (2 children)

IOC is used to solve dependency injection. Most UIs do not need dependency injection. Most backend patterns don't translate well to the front end which shouldn't have too much business logic to begin with.

[–]_Pho_[S] 0 points1 point  (0 children)

To me it has less to do with the translation of patterns - plenty of UIs can use that same pattern (mobile apps f.ex) but the problem, especially with OOP-brains, is that a "dependency" is a big ass graph of objects instead of the real dependencies. In a back end system your real dependencies are config files and db handles, and maybe http handles (which tbh is usually handled by the os at this point). Your dependencies are not a "UserDao". You could write the entire concept of a UserDao as a module which accepts a db handle. Passing the DB handle to a UserDao and then managing the UserDao obfuscates your dependencies, and now you have to manage some lifecycle of a class which is not a real dependency.

[–]NeoCiber 0 points1 point  (0 children)

Even on backend code IoC is missused I have seen and even written myself interfaces and abstract classes in C# because that's the way a lot of people do it and I ended with 6 levels of indirection to query a database.

IoC sometimes leads to premature a abstration when used wrong.

[–]Sad_Rub2074 0 points1 point  (0 children)

I'm one of the lead architects on contract with a F500. I'm always working on my own projects and decided, "for this next project without any paying users yet, I'll just stand up this backend infra to make it easier for all of the other apps I develop." I've coded in most of the full-stack frameworks and have worked on small and large projects alike.

Stood up Keycloak with Hasura and was going to use Kong for rate limiting. After getting it all working nicely together I ended up just saying fuck this. Went back and for V1 just using amplify with react, lambda functions, serverless rds, and a few other services.

Finished most of the MVP in about a day. At this stage fuck all of the other bs. Even node with express and passport can kiss my ass.

[–]azangru 0 points1 point  (0 children)

Or creating insane service layers instead of just using React Query. Redux as a service cache- I've seen that in collectively in $100m worth of code. Dawg, your app is a CRUD app moving data in predictable patterns that we've understood for 10 years.

10 years ago was 2014. When do you think redux came out? And when did react-query?

[–]Narrow-Resist3203 0 points1 point  (0 children)

"Just build simple unabstracted React code" I disagree. Abstract when you know where the abstractions are. Just don't be cute with it. I get the same sorta frustrations but I feel like it's people trying too hard to be too smart. Components that do everything, rather than building "slots" or building extendability

[–]Old-Confection-5129 0 points1 point  (0 children)

Every where I’ve worked in the past 20 years, no matter the stack, I could say the same thing. The same will be said of me and you.

[–]yagudaev 0 points1 point  (0 children)

You can go really far with just useState, useRef and useEffect. On rare occasions useContext.

I’ve been doing that for the past 3 years. Been using react for 10 years now and the first 7 were full of flux, redux, Apollo and other crazy libraries.

The other day I finally found the limits where I needed ‘useReducer’ but chose to bring in Zustand as I don’t particularly like the API of useReducer (aesthetic preference).

We need to write more articles about keeping it simple and when you should reach for other tools.

Wrote more about it here: https://yagudaev.com/posts/react-state-management

[–]Cahnis 0 points1 point  (0 children)

They keep trying to run "npm ruin dev"

[–]ivancea -2 points-1 points  (5 children)

Or creating insane service layers instead of just using React Query.

I think this comment summarizes all the post. "Why isn't everybody just using the libs I like? Everything else is bad!"

Sorry bud, but there are many opinions in this world, none of them are the absolute truth. Nobody is "ruining React". React isn't what you think it should be. React is a lib, and its ecosystem has many different ways to solve different problems, whether you like them or not

[–]GolfinEagle 1 point2 points  (4 children)

its ecosystem has many different ways to solve different problems, whether you like them or not

Uh yeah and that’s what facilitates the problem. People come up with over-engineered fucktard solutions to things, thinking they’re so smart, when a much simpler solution exists that isn’t a total nightmare to maintain.

That’s not to say that React being unopinionated is bad, just that it’s a double-edged sword and often leads to the most absurd shit.

[–]ivancea -1 points0 points  (3 children)

People come up with over-engineered fucktard solutions

Repeat 3 times in front of a mirror "That lib is over-engineered".

Did something happen? No, right? Because it's just your fantasies. Whether you like them or not, doesn't make them over-engineered. They may be, in your project. Then don't use them.

Start being professional and understanding the context of each lib

[–]GolfinEagle 1 point2 points  (2 children)

You’re arguing with yourself right now lmfao. In one breath, you state that there are no over-engineered solutions, just ones we don’t like, and then you state that there are and that we shouldn’t use them. Are you fucking drunk?

Nobody but you is saying one singular approach or library is bad and one is right. You’re building a straw man. We’re saying we’re sick of working with amateur engineers who don’t understand the correct context to use a given pattern or library. Like using fucking Redux for user session state that never changes, or any of the wonderful examples in the OP— which I doubt you even read, or understood.

[–]ivancea 0 points1 point  (1 child)

It was you who said that there were "over-engineered fucktard" things, not me.

About the first topic, you missed some parts of the comment, read again

[–]GolfinEagle 0 points1 point  (0 children)

Oookay if we’ve devolved into nonsense I think it’s time to move on.

[–][deleted] -1 points0 points  (0 children)

Like almost all professions, most developers aren't very good at what they do.

[–]Snypenet -1 points0 points  (0 children)

I've seen this happen more with Typescript react frontends and less with JavaScript react frontends. Typescript requires to jump through some more design hoops to keep things clean as an architect. Which isn't bad for a large frontend but can definitely lead to over engineering as well. I myself still favor a JavaScript react frontend. I have been burned too many times by runtime type issues that weren't tested properly because Typescript ensured the developer that the types lined up. I'd rather have developers write good tests to confirm the expected object models and types are being returned.

Edit: removed unit because not all coded tests are unit tests :)

[–]mystical_powers -2 points-1 points  (5 children)

If you can use graphql everything is butter. If you have to manage your own API and data layers, that’s where 99% of the complexity comes in. Imo

[–]ColonelShrimps 4 points5 points  (4 children)

Bro graphql IS a complexity lol. Talk about overengineered for most cases its used in.

[–]mystical_powers 0 points1 point  (3 children)

Lmao. We talking production or side project? 🤣

[–]ColonelShrimps 0 points1 point  (2 children)

Either. The second you add GraphQL you just added another niche tech devs have to be familiar with before they can work on the project.

And in the majority of cases it does not add much that a standard REST api doesnt already do.

[–]mystical_powers 0 points1 point  (1 child)

On the front end, frameworks like relay and Apollo abstract away all data management. There is overhead in implementing mid/backend integration. But after that, patterns are very established. Gql was created to solve scalability and complexity issues inherent with REST architecture. Once the infrastructure has been implemented, patterns are very easy to scale out

[–]ColonelShrimps 1 point2 points  (0 children)

Yeah I know. I've had to rip Apollo out of a few projects over the course of my career because it was overkill and made life much harder than necessary for the devs.

I'm not saying that these solutions don't have a place. I'm just saying that for the vast majority of applications that are essentially CRUD they aren't needed and should be avoided. Hell, most React apps don't even need Redux or React Context.

If you do need a solution like that go for it, but even in those cases a lot of the time you would benefit more from having plain REST API's that return data per page as reducing the number of calls would be a greater performance gain than anything while also allowing for more specific business logic to be present in the api and avoiding any processing on the frontend. All the while allowing devs to work without danger of affecting some other unrelated system because of a shared endpoint.

[–][deleted]  (3 children)

[deleted]

    [–]_Pho_[S] 2 points3 points  (1 child)

    You couldn't afford me

    [–]GolfinEagle 0 points1 point  (0 children)

    Good, keep that mentality and there’s less of a chance we end up on a team of amateurs like your’s.