Five React App Killing Anti-Patterns 🪦😱

2024 ж. 3 Мам.
29 682 Рет қаралды

Five viewer submitted ways that bad React practices and anti-patterns are killing their applications, and some solutions for each one.
👉 Upcoming NextJS course: pronextjs.dev
👉 Don't forget to subscribe to this channel for more updates: bit.ly/2E7drfJ
👉 Discord server signup: / discord
👉 VS Code theme and font? Night Wolf [black] and Operator Mono
👉 Terminal Theme and font? oh-my-posh with powerlevel10k_rainbow and SpaceMono NF
0:00 Introduction
0:47 UseEffect
4:25 Redux For Everything
6:52 CSS: Pick A Lane
9:09 Super Huge Components

Пікірлер
  • Agree for the most part. I will take a 500 line component over a code base that has too many abstractions tbh. It's easier to search one file than to trace a spiderweb back and forth.

    @FabuBrik@FabuBrik2 ай бұрын
    • I guess, but If someone is that bad at writing abstractions that 500 lines of code is preferable, they prob have more important things needing work. I was that guy though when I started in react. For some reason the idea of applying proper design patterns to front end JavaScript code just didn't click.

      @Dom-zy1qy@Dom-zy1qy2 ай бұрын
    • @@Dom-zy1qy 500 lines isn’t even that much. Much of that could even be imports. All depends on the situation of course but anecdotally I’ve spent far more time and brain power switching between files than scrolling up and down.

      @FabuBrik@FabuBrik2 ай бұрын
    • @@FabuBrik 500 lines defeats the most important benefits of components and that is reusability and readability.

      @radulaski@radulaski2 ай бұрын
    • @@radulaski like I said sometimes it’s more readable in a single file than abstractions would be. It depends of course.

      @FabuBrik@FabuBrik2 ай бұрын
    • ​@@FabuBrik allowing hundreds of lines of code is a certain road to spagetti and doom. It may be your preference but in general it is a very bad idea. You'll be hard pressed to find a CS professor that would agree with you.

      @radulaski@radulaski2 ай бұрын
  • 1. Use useEffect Carefully to Prevent Infinite Loops 2. Use Redux Appropriately for Global State, Not for Local State 3. Standardize CSS Practices in Your Project 4. Break Down Large Components into Smaller, Manageable Pieces 5. Rationalize the Use of Libraries in Your Application

    @shakapaker@shakapakerАй бұрын
  • One of the cases where I find it appropriate to have a big component (>= 250 lines) is when you use recharts library while building complex charts - they can easily get out of hand quickly and due to their limitation, you can't properly make custom components, only by using some hacky-wacky workaround which is not good :(

    @user-iv7ci3hp2u@user-iv7ci3hp2u2 ай бұрын
  • I respect you so much sir, this kind of content we required 😄

    @irfanmohammad7269@irfanmohammad72692 ай бұрын
  • thanks for the tip about Knip, it's great!

    @landsman737@landsman7372 ай бұрын
  • Thank you for the great videos!

    @Blue-bb9ro@Blue-bb9roАй бұрын
  • Anti-pattern: Using context as a solution for state management or to "avoid prop drilling". While you can use it for that, you probably shouldn't. Make your global/shared state live outside React and subscribe to updates where needed. Deep prop drilling is a sign of too much abstraction going on. Instead of reaching for Context, try to simplify your component structure. If some state is updated across components (i.e. shared state), move that state into global state outside of React instead. Context can result some decremental effects, especially as you move it higher up the tree to allow more components to subscribe to it. Contexts are useful for dependency injection within a small and specialized scope, like for example within compound components where each component can read from its parent scope and update attributes or change behavior based on it and it's not trivial to pass props between them (and by non-trivial I don't mean in depth of a tree but in usage)

    @dealloc@dealloc2 ай бұрын
    • I would just recommend against using context altogether. A rule with exceptions is just going to be broken all the time. It's better to be black and white and keep it simple. While Context might result in some boilerplate, you can draw a lot of benefits from having pure code.

      @majorhumbert676@majorhumbert6762 ай бұрын
    • @@majorhumbert676 As I explained above, it depends on what API you're trying to provide. Sure you could just export hooks and have someone setup components by passing props manually, like React Aria. But compound components (like Radix) are a useful pattern where Context is the only mechanism that allows you to pass state between the components in the tree, without leaking internal API details and doesn't require the user to wire up everything themselves, just styling. This makes sense when you want to provide sane defaults as a component library. There are uses for it, but it's mostly related to passing dependencies within a well-defined scope.

      @dealloc@dealloc2 ай бұрын
    • Understanding and appropriately using the Context API is also important. The Context API is not a state management API, but it is a good solution if there is excessive props drilling. Additionally, the Context provider does not necessarily have to operate at the very top; it is better to place it as close as possible to the components that need to share state.

      @user-qs6lb3dz5o@user-qs6lb3dz5o2 ай бұрын
    • Now that’s something I’ve been using Context API for and has turned a few heads - as a DI container for features to decouple user value from toolchain (which in this ecosystem just changes way too often)

      @rafaelrocha3991@rafaelrocha39912 ай бұрын
    • @@rafaelrocha3991 It depends what you are injecting and how much. It makes sense as an enhancement to existing pieces, which is what I assume you use it for-like providing features that components can use conditionally. But using context purely to make your code "easier to test" just to avoid props or use of mocks makes it difficult to convey which components require which providers since you are introducing implicit constraints that cannot be easily linted or type checked. That's also why I recommend our team to always provide sane default context values for contexts, and otherwise rethink their approach if they can't.

      @dealloc@dealloc2 ай бұрын
  • Thank you, Uncle Jack!. And please make a video regarding Tanstack Router.

    @presida3927@presida39272 ай бұрын
  • Good you mentioned these barrel index files. Seems like lots of people use it and recommend for defining clear interfaces to communicate with a particular feature, and it makes sense. Until you try code splitting and notice it doesn't work as expected.

    @jakubsalanyk8830@jakubsalanyk88302 ай бұрын
    • But it does work if you configure it properly. Vite through Rollup config, Webpack, Rspack, esbuild and parcel all support the SideEffects tree-shaking config, which lets you configure which exports have side effects via a string or an array of glob patterns

      @privateanon7623@privateanon7623Ай бұрын
    • @@privateanon7623 Yes and no. You can do that, but I never saw anyone sucessfully implemented such optimization for an _app_ Of course u can do that for a library, as it just smaller, easier to manage, and have backed-in isolation I would really like some content/resources to learn, on how to properly manage barrels, without manually adding those into package.json(and bursting cache for your monorepo tasks) and/or without posibility of shoting yourself into the foot by accident if you would have side-effect(and how to manage those situations)

      @nazarshvets7501@nazarshvets7501Ай бұрын
  • Thanks!

    @codefinity@codefinity2 ай бұрын
  • Spot on! throwing all in to a big Redux store probably the worst !

    @samithafernando6432@samithafernando64322 ай бұрын
  • Hey Jack, could you do a deep dive on barrel files. They are so convenient, i know it's not really something important but i hate seeing many lines of massive import strings. I'd love to hear your thoughts on the barrel file pattern, more on why it's bad and if there is any other patterns that are better for grouping related code.

    @danielkeefer1901@danielkeefer19012 ай бұрын
    • Agree, barrel files hides your module implementation details, which helps a lot, during future refactoring. For example if you have changed file name or module files structure you need to change imports only in one barrel file, otherwise you have to change import across whole project and its very annoying in big projects with different codeowners per folder, and get messy on code review.

      @RockyTheDog756@RockyTheDog7562 ай бұрын
    • And I’ve never heard that it creates some problems for bundlers, but even if it’s do. It’s better to have problems for bundler then for developers!

      @RockyTheDog756@RockyTheDog7562 ай бұрын
    • Bundlers also solved this a long time ago. You can define a sideEffects prop that's supported by all the existing bundlers, where you specify - via a string or an array of glob patterns - which files have side effects, so others can be pruned when not used in imports, via tree-shaking.

      @privateanon7623@privateanon7623Ай бұрын
  • TanStack Query - one love

    @alexeyzhabin@alexeyzhabin23 күн бұрын
  • I remember seeing really weird behaviour from a forwardref component that seemed deeply entangled within an app. It returned an array of fields and some fields re-rendered more times than others. Managing state was way too complex for my skills. The entire form state was deeply nested in global state somewhere and local state was difficult to manage because of how the fields are reused - either a field would go missing or had stale state and showed the wrong properties. Ended up easier to write logic directly in the return rather than bringing it out to simplify things.

    @archamedis@archamedis2 ай бұрын
  • The kitchen junk drawer! (Totally on my list to clean tomorrow)

    @Stevie1derson@Stevie1derson2 ай бұрын
  • thx for article

    @rmltsn@rmltsn2 ай бұрын
  • hmmm I do that barrel files pattern, but only for small files like global constant, global config, global endpoint, essentially anything that global. I didn't know that it is named barrel, but I want to explore more of that to rethink my decision on our projects. Thank you, sir! 🚀

    @DioArsya@DioArsya2 ай бұрын
    • When you say globals do you just mean cosntants. If so, that's probably ok. The problem is really when the barrel file in turn makes a lot of imports and re-exports those. Those don't get pruned in development mode so they significantly slow down the DX if you use them.

      @jherr@jherr2 ай бұрын
    • check out sideEffects config prop in webpack/rspack/parcel or through rollup in vite. It's specifically made to solve the tree shaking problem in barrel files that you were discussing in the video @@jherr

      @privateanon7623@privateanon7623Ай бұрын
  • I am a new react developer, I jump from vue because I feel react is much more flexible and creative for developers. It’s more fun to construct things in your own way. I will take this video seriously and try a new exercise in frontend mentor

    @jasper2virtual@jasper2virtual2 ай бұрын
  • 💯

    @fedoskamcha3768@fedoskamcha3768Ай бұрын
  • Hi Jack, can you make video on how to build two different microfrontend app in typescript react and deploy them on aws s3 bucket and consume them.

    @webcoderspeed@webcoderspeed2 ай бұрын
  • Awesome, I can't agree more. These anti-patterns are very important to be aware of.

    @Mo.Faried@Mo.Faried2 ай бұрын
  • Hello. I'm enjoying the video :) I accidentally opened the explanation and found the last 10:36 min 1. Library overload missing

    @Geuni620@Geuni6202 ай бұрын
  • With objects, the dependency array looks at the reference id values, not a reference itself. Too many devs incorrectly think objects are passed by reference but they are always passed by value (which is a copy of the reference id, not the reference - big difference).

    @kevinbatdorf@kevinbatdorf2 ай бұрын
  • 0:41 That naming 💀

    @gercius@gercius2 ай бұрын
  • Go next top of anti-patterns

    @popuguytheparrot_@popuguytheparrot_2 ай бұрын
  • This is unintentionally a Vue advertisement.

    @semyaza555@semyaza5552 ай бұрын
    • Haha. For Vue developers, they pick Pinia and it's sweet. No need to dig among Redux, Recoil, Zustand, Jotai, Hookstate, MobX, etc; sometimes maybe immer, valtio 🤣

      @WilliamShrek@WilliamShrek2 ай бұрын
    • Jotai's atom is very simple to store and access data like useState. 😊

      @vetrivendhan6122@vetrivendhan6122Ай бұрын
  • How would you refactor a component that only has a form and several input components which makes it >300 LOC?

    @tasin5541@tasin55412 ай бұрын
  • Could you possibly create a tutorial video on how to set up and configure testing in Reactjs + Vite (vitest + react testing library)? Because create react app came with jest and it was easy but Vite does not come with jest…

    @JoonasKarp@JoonasKarp2 ай бұрын
    • but it comes with vitest, share same config for testing, so you pretty much setuped from get-go (if you don't need coverage, e2e, or any specific framework for testing) Just write a test, and run it ☺

      @nazarshvets7501@nazarshvets7501Ай бұрын
  • Knip is great for cleanup

    @nikhilpsathyanathan@nikhilpsathyanathan2 ай бұрын
  • I have been to one React project for experience after finishing the GoIT courses. The reality of that project was that people are making 500 to 700 lines components and don't want to refactor them into smaller once because they are lazy and they don't care about your opinion at all. As long as their code works, the Project Manager is satisfied. The complains of developers with more "refined" taste for code are being ignored. So, basically, as long as devs make features, and everything works, nobody actually cares. Once your code start to be a cause of problem, then PM may ask you to rework it to something better. The decision maker of the project is in charge of the assigning people to do the refactor job. If you just tell someone to refactor, and you do not controll these people, it means your best intentions are in vain. People listen to their leader only, the one who is in charge and possibly may pay in the future, whom they depend on.

    @codeChuck@codeChuck2 ай бұрын
  • I believe that barrel files are fine as long as you take care that their scope does not blow up.

    @radulaski@radulaski2 ай бұрын
    • All things in moderation.

      @jherr@jherr2 ай бұрын
  • I’m not sure I agree with the hard limit on LOC for comps. Like in some cases the JSX is long but the actual functionality isn’t or even what’s being done in the component is just calling hooks with a bunch of params which is still easy to read but long. So I think it depends but if I see a long component doing a lot of stuff with 600+ lines yeah I’d be mad

    @antoniocestari5775@antoniocestari57752 ай бұрын
  • Where does the store (redux store) keep its data? Where do other store providers keep their data?

    @richardflosi@richardflosi2 ай бұрын
    • In memory, but it can be persisted in localStorage / sessionStorage

      @Kwuala@Kwuala2 ай бұрын
    • Outside of React*. Components subscribe to the state and re-render when state is updated. It can be as granular as needed.

      @dealloc@dealloc2 ай бұрын
  • This video was interesting from start to end. The one thing I can't wrap my mind around is the 50-lines-long component. I measure my components in terms of complexity and responsibility and have never reached 50. Experience may show me how.

    @kikevanegazz325@kikevanegazz3252 ай бұрын
  • zustand forever

    @varandz@varandz2 ай бұрын
  • On your point about using a single state managers. It depends what those state managers are used for. Most state management libraries are general purpose and great for custom business logic, but others also provide specific state management, like react-stately for ARIA compliant components, React Query for caching async results, or form-specific state management. It's OK to use multiple state management libraries, but for each their purpose.

    @dealloc@dealloc2 ай бұрын
  • I support the continued use of Redux and don't understand the urge to re-implement it using hooks for every app that we write. Most application developers don't have the time or know-how to create hooks code that rivals redux in maintainability and performance.

    @elliotyoung1291@elliotyoung12912 ай бұрын
  • Aren't they discontinuing or leaving the maintenance for Redux?

    @KorhalKk@KorhalKk28 күн бұрын
    • Not that I know of. Redux is still under active development. But there are lots of other state managers out there now (Zustand, MobX, Jotai, Recoil, XState (sort of), etc.)

      @jherr@jherr28 күн бұрын
  • My issue is always googling to see how to organize my files, components and types 😭

    @Infinitay@Infinitay2 ай бұрын
  • I feel Redux reducers are anti-patterns, business logic must be separated with creational patterns for unit testing. Also complex conditions in the component are hard to read, they must be moved out of the component.

    @vetrivendhan6122@vetrivendhan61222 ай бұрын
  • Hating long components as an arbitrary limitation is silly to me. Sometimes you may have a larger context provider pulling together several bits of data and doing derived data transforms in useMemo hooks, or sometimes you just want to reduce indirection during your dev flow and work in 1 file. Splitting into many files for the sake of organization seems like a premature optimization to me. If scrolling is annoying, use your IDE's symbol lookup shortcuts to navigate quickly!

    @docmars@docmars2 ай бұрын
    • Yeah, abstracting things based on lines of code is really silly. Of course don't create 1k+ line components all the time, but splitting things into 50 components that are each 20 lines of code doesn't make it magically better or more readable/comprehensible. It might make that single component easier to understand, but how all these 50 components integrate together might be super hard to wrap your head around. Regarding larger components, I think it also helps if you are consistent with your component structure. I usually order things the same way so all components that I write have basically the same shape: - static values outside the component. I might have some value being used in multiple places to configure the component, but that value doesn't depend on state or props, so I put it outside the component. Best if I have an object with some values so I don't put it inside the component body where it would get re-defined on each render - inside the component function body, basic state goes first (useState/useReducer) - 3rd party hooks or custom hooks (useRouter, useMyQuery, useWhatever) - useEffect - useMemo - simpler computed variables (e.g. "const isSearchViewActive = !searchInput.isEmpty && whatever.length > 0") or something like that. useMemo just isn't required here, it's not an expensive computation. Those are named variables that I then use in JSX to render things conditionally or pass as a value to other components - JSX

      @rand0mtv660@rand0mtv6602 ай бұрын
    • I agree with this wholeheartedly. Refactoring after you have it done so maintenance is easier, sure. Starting with 15 files? That's a sure-fire way to get confused.

      @developersteve1658@developersteve16582 ай бұрын
    • You'd be surprised of how many programmers are okay with components with thousands of lines. Where I work, even the programmers who do acknowledge that our 5000 lines components are problematic refuse to do anything about it. Kill me.

      @majorhumbert676@majorhumbert6762 ай бұрын
  • Redux is beautiful. Its people's fault if they dont know how to use it

    @jellyfish1772@jellyfish17722 ай бұрын
    • Couldn't agree more. So many people seem to prefer using the same tool for everything.

      @gransmistad323@gransmistad3232 ай бұрын
  • Hooks.

    @PeterThomsen-fg4mv@PeterThomsen-fg4mv2 ай бұрын
  • You think 250 lines is crazy? I work in codebases with components over 3,000 lines... Debug city

    @jaminroberts2333@jaminroberts23332 ай бұрын
  • -+2000 lines of a single component, with a hundred of them. And all of that is a hand over projects, so yeah, this is real life, dude. Real life.

    @DioArsya@DioArsya2 ай бұрын
  • Fun fact. Leetcode lighthouse score is only 53 points😂. Too much libraries.

    @tomfancode@tomfancode2 ай бұрын
  • 50 lines for component is Clean Code take(L) Can't wrap my head my would you guess how such component will evolve to not have a refactoring mess for every change. Over-abstraction and/or over-decomposition can create situations where you would have to many pieces to compose, making it hard to maintain (kinda rxjs amount of operators problem, with an exception, what you don't have time to refine all of components on every change to any of such component). Such desicion can age poorly

    @nazarshvets7501@nazarshvets7501Ай бұрын
    • just write it in, if you spot several layers of abtractions intervined within such component, you can extract lower level implementation and abtract it out If there is no clear way to split it, and it doesn't make your life miserable just leave it there for the next change request. For me anything that less than 500 lines its ok, as long as its comply with previous points. Should point out, that I have hard-divide rule for a component - if it have more than 20 lines of none-jsx stuff in it, I will extract all of that in coresponding separate file(s) to deal at one complexity at the time (separation of logic and view as jsx)

      @nazarshvets7501@nazarshvets7501Ай бұрын
    • also, I often work with comboboxes and datagrids, which are highly tailored for each usecase (no clear way to generalize it, at least while we at rapid development cycle), so 100 lines in components its basic boilerplace that I copy-paste before I start to customize it

      @nazarshvets7501@nazarshvets7501Ай бұрын
  • I hate long components, I put a lint rule for 300 lines for component files. That I then proceeded to turn off because some of my component files were 350+ lines. I still feel like ~100-150 lines is a relatively simple component though. One monster I've seen was 800 lines of super complicated nested conditional logic with just one component, I managed to split that at least. But a few remained. And I absolutely agree, redux needs to die. There are so many better alternatives. Tanstack query + zustand cover basically every use case while being way less complicated. And althrough you could argue "two state management libraries, that's worse", I think getting two smaller libraries that are specifically built to handle their respective side of the state is a better option.

    @helleye311@helleye3112 ай бұрын
    • That's nothing: where I work, we have countless components with over 1000 lines, and many components with over 5000. Last week in a code review, I proposed that we simply extract some inline SVG markup into a component, but that got shut down.

      @majorhumbert676@majorhumbert6762 ай бұрын
  • Worth mentioning here in comments about Jotai and Nanostores for state management and DaisyUI as great TailwindCSS Component library (IMO better than Shadcn) 👨‍💻

    @DeffQ@DeffQ2 ай бұрын
  • These are some of the reasons I’m moving away from React. So many rules and caveats it’s just crazy. I’ve used Angular and Vue for years and never thought I was stupid. React made me feel stupid af. I went back to Vue and it’s heaven.

    @charlie64x2@charlie64x22 ай бұрын
  • Redux-saga is so good for unit/integration testing. Shame I can't use it outside of redux

    @matttamal8332@matttamal83322 ай бұрын
    • Why can't you? Redux isn't bound to React. Is Redux Saga?

      @jherr@jherr2 ай бұрын
  • Big components in many cases are fine. I'd rather see more at once than have to dive into 20 components to understand whats going on. Also a big component for me is >= 1000 loc

    @abel090713@abel0907132 ай бұрын
    • Too many. My max is 500

      @Marasma101@Marasma1012 ай бұрын
  • People keep telling me that using react-query as state management is an anti-pattern, but it just works and solves my problems. Am I crazy?

    @Cahnisama@Cahnisama2 ай бұрын
    • Do you really use it for "state" or do you just use it to "sync with the server"? Pulling data from an API using react-query is not state management, at least not to me. Most apps are CRUD apps anyway and you don't really need state management, you just pull data from the server and do POST/PUT/DELETE requests when needed.

      @rand0mtv660@rand0mtv6602 ай бұрын
    • @@rand0mtv660 I use it for both server-state (sync with the server, AKA fetching and caching data), and also for storing client-state (aka, global state) and using it to inject the data into the components

      @Cahnisama@Cahnisama2 ай бұрын
  • 1. antipattern use of react. you might dont need it, also you might make it worse with react.

    @dmytroportianka3842@dmytroportianka38422 ай бұрын
  • I can't wait till the KZhead influencers realize that the double GET hack is a HACK and was never necessary. Don't get me wrong I reach for react before anything

    @buddy.abc123@buddy.abc1232 ай бұрын
  • The key takeaway from the video is to Stop Using React. This framework doesn't help you write good code; it only complicates and confuses, forcing you to seek auxiliary tools and jump from one to another.

    @wswebus922@wswebus9222 ай бұрын
    • To be honest, I like when people (usually they also happen to be positive people) say what they do recommend according to their experience rather than exclusively what not... This is why this video was great.. (in contrast to this comment) - For every "how not to do something" there was always the correct way to do so. Cheers!

      @wishmeheaven@wishmeheaven28 күн бұрын
    • @@wishmeheaven you’re right. You can use Vue, Svelte, Solid, Astro, Alpinejs and all these frameworks don’t have so much pain that you’ll have using React

      @wswebus922@wswebus92227 күн бұрын
  • It's been more than a year now I do not recommend react to my clients, because I think react is the anti-pattern here.

    @RachidBoudjelida@RachidBoudjelida2 ай бұрын
  • Just don’t use React! Use Angular 17

    @xxXAsuraXxx@xxXAsuraXxx2 ай бұрын
  • Can you collaborate with @theo-t3? I love to hear both of you arguing 🤣

    @joshuagalit6936@joshuagalit69362 ай бұрын
KZhead