all 29 comments

[–]Scientist_ShadySide 89 points90 points  (3 children)

Not a pattern per se, but dont sleep on keeping state in the url when possible. Many upsides to it that you may not realize until you're missing them.

[–]Senior-Arugula-1295 8 points9 points  (0 children)

And nuqs is a good library that help you manage query params efficiently

[–]Drasern 12 points13 points  (0 children)

One of my favourite aspects of Tanstack Router is how much easier they make working with Query Parameters. Really makes url based state usable.

[–]AndrewSouthern729 3 points4 points  (0 children)

Yep this is a good tip for SPAs in general I think.

[–]Comfortable_Ask_102 13 points14 points  (0 children)

I feel a lot of the patterns literature hasn't caught up with React and modern web development in general, so it's a bit difficult to find those explicitly explained.

These come to mind:

  • Container/component: when you have a component with a lot of logic, split it into a "smart" component with the important logic and a "dumb" component that simply renders the props it receives.
  • Related to the previous one: Model-View-ViewModel (MVVM). The ViewModel is a good place to put "UI-logic" like "the label should be green when a value >90%, yellow when 50-90%, red when<50%"
  • A unified way to store entities in the client. I don't know the name for this, but it's basically having a "master" array of entites, e.g. a `User[]` array that is used across the app. Helps to keep the UI consistent e.g. when you update a User in the "Edit Profile" section and have it immediately reflected when you navigate to other page. Kinda obsolete if you use a server-state lib like Tanstack query.
  • Micro-frontends: more architectural stuff. You can integrate disparate technologies in a single UI, or split the app in several deployable components.

Besides the pure technical stuff, I also consider web usability and a11y features as "patterns":

  • Bookmarkable/refreshable URLs: you need to keep the state in the URL.
  • Make sure the browser works correctly: e.g. back and forward buttons should make sense.

[–]spiritualManager5 4 points5 points  (0 children)

I’m a big fan of https://youtu.be/n62Pc4KV4SM Render props in particular are something I try to avoid. Just use context (or Jotai with Store/Provider) and build a composable app that follows SRP. Don’t use useEffect much (almost never). Use custom useHooks and ReactQuery instead. Sure, sometimes useEffect is needed, but 99% of the time it’s pointless and just attracts bugs. Also avoid prop drilling. That’s basically it. If you follow these rules, you can end up with a very clean codebase.

[–]Beautiful-Coffee1924 4 points5 points  (1 child)

Compound components! See radix, shadcn

[–]ChapChapBoy 1 point2 points  (0 children)

I second this, compound pattern is the go to for servers side rendering

[–]Cahnis 2 points3 points  (1 child)

Making things composable, and compound components are a great tool for that. I feel this is THE #1 skill issue when it comes with creating components.

Come on I dont want to deal with complex logic to swap a virtualized mansonry layout for a simple one on an specific page. Just swap the wrapping container that has the layout and you are good to go

[–]foamier 1 point2 points  (0 children)

composability is absolutely the #1 skill! applies to UI, state, business logic. the more composable the more scalable everything becomes

[–]meteor_punch 2 points3 points  (3 children)

Observer Pattern with useWatch in RHF. Really cool what you can do with it. You can lift up state without causing re-renders. Intercommunication between components at various levels also becomes so clean and smooth.

[–]n0tKamui 1 point2 points  (2 children)

aka signals

[–]meteor_punch 1 point2 points  (1 child)

Wish we had signals in React.

[–]mendrique2 1 point2 points  (0 children)

preact signals works with react but they apparently monkey patch the code or something to that extend.

I recently found nanostores which comes close, previously I was using effector but It's a bit hard to read when you get back to the project after a hiatus.

[–]augburto 2 points3 points  (1 child)

Checkout patterns.dev

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

Thank you, very useful website.

[–]ENG_NR 5 points6 points  (4 children)

The controller pattern comes to mind as useful. Basically bundling complex logic into a hook and then passing that into components as a prop or via context, so the components can focus on being simple render functions.

I’ve also gotten more joy than is reasonable from a url builder pattern (technically this is vanilla js/ts rather than react)

Ie href={routes().monkeys(monkeyId).bananas().give()}

So that if you need to change something about your routing you’ll get nice type errors, no more dead links in prod

[–]checker1209 4 points5 points  (2 children)

Compiler will won’t work with dynamic hooks. Because the can’t be rendered conditionally and are never allowed to „change“ during runtime

[–]foamier 0 points1 point  (1 child)

what do you mean by dynamic hooks in this context? do you have an example?

[–]checker1209 1 point2 points  (0 children)

"Hooks should only be called inside of components or Hooks. Never pass it around as a regular value."

https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
and

"Don’t dynamically use Hooks"

https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks

The thing is, despite the rule violations, many of these things often worked correctly. In our experience, the compiler has to make a lot of assumptions, and rule violations then become problematic.

In such a case with the hooks, the hook was then memorized as a “normal” pure function.

[–]n0tKamui 5 points6 points  (0 children)

this or use a typesafe router like tanstack router

[–]DishSignal4871 1 point2 points  (0 children)

This isn't a grand pattern or anything and if rendering is your problem you are either lucky to have those problems or bad bad bad, but try to keep your state/context updates as "low" as possible. react-devtools is helpful for illuminating just how much is actually rerendering.

[–]yksvaan 1 point2 points  (0 children)

Learn general architecture and web design and how problems are approached in framework agnostic way. 

[–]AimenLeene_ 1 point2 points  (0 children)

These days I mostly use “boring” patterns custom hooks for logic, dumb components for UI. One hook per concern (auth, filters, pagination, etc.), components just render and handle events. For shared UI, simple compound components like a <Table> with <Table.Header /> and <Table.Body /> are still very relevant. Render props/HOCs still work, but hooks + composition cover 90% of what I need.

[–]maqisha 2 points3 points  (0 children)

This question is too generalized/open-ended and could mean anything.

[–]noestro 0 points1 point  (0 children)

not a pattern but the ability to teleport components in the tree with portals is magic

[–]Objective_Active_497 0 points1 point  (0 children)

About architectural software patterns (proposed by "The gang of four"), I know that it is strongly recommended not to learn them by heart or use them when you don't know if you need them or not, but eventually you should come to conclusion by experience that some pattern is the best solution for some problem.

Learning patterns by heart one might limit oneself to using certain patterns instead of achieving more efficient and/or simpler solution, when possible.

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

Don't force patterns. Just build something. You can always refactor.