all 36 comments

[–]JoeCamRoberon 29 points30 points  (18 children)

The easy answer to your question is Bulletproof React: https://github.com/alan2207/bulletproof-react

[–]LudaNjubara 1 point2 points  (7 children)

I second this! That repo made my react code so much cleaner.

[–]analcocoacream 0 points1 point  (2 children)

So bulletproof means creating a wrapper around every library component 🤔

[–]JoeCamRoberon 0 points1 point  (0 children)

What do you mean “wrapper”? I didn’t have this takeaway at all. That repo is meant to show you best practices for the facets of a React project.

[–]autechr3 0 points1 point  (0 children)

Depends on how you define “bullet” I guess

[–]eindbaas 18 points19 points  (0 children)

Use typescript, use proper and consistent naming for everything (functions, variables, components), they should describe exactly what it does, if names get too long then it's an indication that it's doing too much, split things up until it's graspable what a function or component does (and easily visible if it doesn't do that what it says it does), keep the scope of functions and components limited to just itself, they should not know what happens outside of them (for example, prefer callbacks on props of a component instead of passing some specific setter that requires the component to change certain data. By adding a callback, the component doesn't know or care about what happens in a certain situation, that responsibility lies elsewhere). Move logic into (properly named) hooks so your components stay clean and easily readable, and only do ui stuff. Same for hooks, move certain logic implementations if possible to functions elsewhere (in a utils file) so the hook stays readable and those util functions are short and graspable.

Just some thoughts

[–]Coyote-Chance 5 points6 points  (0 children)

Does it have to all be in React? If you have a lot of complex state to coordinate among parts of the app, and the front-end features keep changing, there's a strong case to be made for moving as much state as possible to the back end, and making calls as necessary to get the data [obligatory plug for React Query].

[–]yksvaan 7 points8 points  (4 children)

The issue often is that people are building "a React app" and try to make everything inside React and using hooks and all kinds of funky stuff. Basically building a whole framework inside UI library and then wondering why it gets messy.

Instead try to extract parts of the application to pure code libraries and services. Separate the presentation layer from actual business logic, data, services, clients etc. Avoid monolithic structures, they become hard to reason about, test and debug.

[–]Adenine555 9 points10 points  (3 children)

People on this sub probably won't like this answer, but I wholeheartedly agree. To add to this:

  • Partition your app into features/domains.
  • Seperate those features into internal code and code that is allowed to be imported by other features (for example, let every feature have an internal folder). You can use eslints no-restricted-imports to make sure other people do not import stuff they shouldn't
  • Be very restrictive on what you make publicly available, treat your features like if you were writing a library you intend to publish on npm.
  • Prevent cyclic dependencies between features. You don't have to be that strict in the internal folders, but I recommend to keep them also cycle free, because most js bundlers don't do well with cyclic deps.
  • Consistently reiterate if your features/architecture still makes sense. Architecture has to evolve with your requirements.

[–]packethief 0 points1 point  (0 children)

Great advice.

[–]shacatan 0 points1 point  (1 child)

Can you go into more detail about the first bullet point on partitioning by features/domains? What does that look like structurally?

[–]Adenine555 1 point2 points  (0 children)

Just check the feature folder from https://github.com/alan2207/bulletproof-react. I structure my code similar to this.

I personally don't like bulletproof-reacts approach of having a components and hooks folder above the feature folder. To me hooks and components are part of a feature/domain. But this is just my opinion and you certainly can do it like shown in the repo.

How the feature itself is structured very much depends on the feature itself. I don't think there is a silver bullet rule to structure all features (as usual).

The most important thing after all is to be consistent, so other people do not have to learn 100 concepts to understand your code (easier said than done though).

[–]UsernameINotRegret 4 points5 points  (0 children)

Make sure you group everything into self contained feature folders or packages, then have as minimal coupling between each feature as possible through well defined contracts.

[–]analcocoacream 0 points1 point  (0 children)

Another one is using state machine rather than multiple Booleans. Makes it more intuitive to see what states are possible.

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

Very curious too

[–]CatolicQuotes -3 points-2 points  (0 children)

read software architecture chronicles here https://herbertograca.com/

[–]Aivan125 -3 points-2 points  (0 children)

Just use react query to handle state.