GithubHelp home page GithubHelp logo

alan2207 / bulletproof-react Goto Github PK

View Code? Open in Web Editor NEW
22.8K 192.0 2.1K 1.89 MB

๐Ÿ›ก๏ธ โš›๏ธ A simple, scalable, and powerful architecture for building production ready React applications.

License: MIT License

Shell 0.03% JavaScript 8.88% Handlebars 0.46% HTML 1.08% TypeScript 89.30% CSS 0.26%
react react-applications react-best-practice react-typescript react-architecture-patterns react-guidelines react-project-structure

bulletproof-react's Introduction

Bulletproof React ๐Ÿ›ก๏ธ โš›๏ธ

MIT License CI

A simple, scalable, and powerful architecture for building production ready React applications.

Introduction

React is an excellent tool for building front-end applications. It has a diverse ecosystem with hundreds of great libraries for literally anything you might need. However, being forced to make so many choices can be overwhelming. It is also very flexible, you can write React applications in any way you like, but that flexibility comes with a cost. Since there is no pre-defined architecture that developers can follow, it often leads to a messy, inconsistent, and over-complicated codebase.

This repo attempts to present a way of creating React applications using some of the best tools in the ecosystem with a good project structure that scales very well. Based on my vast experience working with different codebases, this architecture turns out to be the most effective.

The goal here is to serve as a collection of resources and best practices when developing React applications. It is supposed to showcase solving most of the real-world problems of an application in a practical way and help developers write better applications.

Feel free to explore the codebase to get the most value out of the repo.

Disclaimer:

This is not supposed to be a template, boilerplate or a framework. It is an opinionated guide that shows how to do some things in a certain way. You are not forced to do everything exactly as it is shown here, decide what works best for you and your team and stay consistent with your style.

Table Of Contents:

Contributing

Contributions are always welcome! If you have any ideas, suggestions, fixes, feel free to contribute. You can do that by going through the following steps:

  1. Clone this repo
  2. Create a branch: git checkout -b your-feature
  3. Make some changes
  4. Test your changes
  5. Push your branch and open a Pull Request

License

MIT

bulletproof-react's People

Contributors

alan2207 avatar bartstc avatar caocuong2404 avatar cassler avatar dc7290 avatar dpyzo0o avatar ebof1223 avatar fishmandev avatar j-miyake avatar jnorris441 avatar madhusudan-kulkarni avatar miily8310s avatar na-ji avatar nanzm avatar neighborhood999 avatar nina1012 avatar oliviertassinari avatar omarefg avatar pfcodes avatar phongluudn1997 avatar ryota-murakami avatar sarahsga avatar sevenoutman avatar sinchang avatar texmeijin avatar theodorosploumis avatar thibaut-decherit avatar w01fw00d avatar y-hsgw avatar yhunko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bulletproof-react's Issues

Project structure: api directory and graphql

What do you think about organizing graphql api as follows and importing everything from api folder?

api
|
+-- fragments              # one file per fragment (default export) + index.js to export everything (named export)
|
+-- mutations              # one file per mutation (default export) + index.js to export everything (named export)
|
+-- queries              # one file per query (default export) + index.js to export everything (named export)
|
+-- subscriptions              # one file per subscription (default export) + index.js to export everything (named export)
|
+-- index.js              # entry point for the api, exports everything except fragments

Many thanks in advance.

Mauro

Dependency cycle

lib/auth.tsx
import { loginWithEmailAndPassword, ... } from '@/features/auth';

features/auth/components/LoginForm.tsx
import { useAuth } from '@/lib/auth';

Wouldn't this Dependency cycle?

Access control at route/action level?

Hi, thanks for this nice project structure!

I find access control is also an everyday topic in a react app, could you give some suggestions on integrating access control (at route and action level) in this structure?

About features/feature folder rules

Thanks for the great resources : )ใ€€ใ€€
I am designing an application based on this document, but I have a question.

What I want to ask you

project-structure.md

A feature folder could also contain other features (if used only within the parent feature) or be kept separated, it's a matter of preference.

  • For the definition of the bolded part

Specifics

Although it is defined to be used only within the parent feature, ใ€€ใ€€
features/comments is referenced in features/discussions, lib/authorization.tsx.ใ€€ใ€€

Also, features/users is referenced in features/comments, lib/authorization.tsx, and route/protected.tsx.ใ€€ใ€€
Aren't features that are imported as new features supposed to be used only by the parent feature that imported them? I wondered.ใ€€ใ€€

However, when I took a closer look at the source code, I found that the part I was wondering about had one thing in common.ใ€€ใ€€
It was that I had imported the Typescript types used in the functional folder.ใ€€ใ€€


Based on the above, I would like to ask you three questions.

  • Can I import the types defined in TypeScript, since they are not features themselves?
  • features/comment is used in features/discussions, but
    Can a feature other than features/discussions use features/comment?
  • featureA <- featureB
    featureC <- featureA
    Is this kind of dependency possible?ใ€€ใ€€
    I can't provide a specific situation where this is needed, but I would like to know if features can be used as grandchildren in features.

Shared/Common api location ?

Hello.
Quick question: Where would you put shared react-query wrappers? Say one were to have a modal dialog that is used by multiple features (and therefore lives in /components) and that is responsible for loading something from a server endpoint...
Cheers

Enable discussions on this repository

I've really empathize these README section.

The goal of this repo is to serve as a collection of good practices when developing React applications. It is supposed to showcase solving most of the real-world problems of an application in a practical way and help developers writing better applications.

I have a project create-react-app-typescript-todo-example-2021 on similar mind,(It's not high quality though ๐Ÿ˜…)

And @markerikson also planed close concept website React Community Tools and Practices Cheatsheet .

I like those project even though this topic contained a lot of subjective things.
I hope to we got space for exchange information about practice that doesn't matter each developer's preference/style/opinion.

Actually I don't know ideal roadmap to the goal even though this repository showing Github trend page these days,
So if Github Discussions available visitors may create some topics or answer some questions or surveys, and the communication of information exchange may flourish.

Do you have a plan about setup Discussions on here? ๐Ÿ‘จโ€๐Ÿ’ป

Correct place for `User` type?

Hi, I've been struggling with this confusion for some time. Here's what features I'm having in my application that is relevant to the User concept.

The auth feature

One option is to bind User type with the auth feature because without the authentication/identity logic in the application, it makes no sense of a User concept.

The admin feature

The admin feature has a user management module which may need a User type that is slightly different from the User of the auth feature. The key difference is that User in admin feature represents "others" or "the User resource", while User in auth feature represents "the current user itself". They may have slightly different properties or they can also be completely different in shape. The solution is not difficult so far. I can simply have two separate User types in those two features and perhaps name one of them AuthUser for distinction (like what happens in this demo repo).

The team feature

Here comes the problem. Now I have this third scenario of a User type where non-admin users need to query other users in the system. They query who's out there and invite them as member of their teams. Now I don't think it make sense to use AuthUser type here because this query is apparently for "the User resources", but I also don't think it make sense to import the User from admin feature because this team member function is not topologically dependent on the admin feature. I mean, I could even drop all admin features without breaking other parts of the application as a non-admin user, right?

So here's 2 options for this problem.

Option 1
Make a third User type that separates from AuthUser and User in admin feature. (Doesn't sound so good)

Option 2
Move the User from admin feature to somewhere a base User should be placed, and import it into the admin feature where its needed. AuthUser may also inherit from this base User type if compatible. (Makes more sense to me)

Either way I need to find a right place for this base User type. I'm now considering putting it in the src/types folder, or in the misc feature. Hope to hear your thoughts and suggestions.

Storybook crashes. Outdated AppProvider import source.

Steps to reproduce

Standard clone repo, install, and then run storybook yarn run storybook.

Error

Crashes due to missing ../src/context in .storybook/preview.js (AppProvider import).
AppProvider was moved during updates to project src/ structure.

Fix

File: .storybook/preview.js
Line: 2
Changes:
import { AppProvider } from '../src/providers/app';

Documentation needs similar loving attention.
File: docs/error-handling.md
Line: 13
Changes:
[Error Boundary Example Code](../src/providers/app.tsx)

useQuery - No overload matches this call.

I am getting this error for all instances when useQuery is used.

TypeScript error in C:/Users/abcdef/vscodeProjects/bulletproof/src/features/comments/api/getComments.ts(22,10):
No overload matches this call.
  Overload 1 of 3, '(options: UseQueryOptions<Comment[], unknown, Comment[], string[]>): UseQueryResult<Comment[], unknown>', gave the following error.
    Argument of type '{ queryKey: string[]; queryFn: () => Promise<Comment[]>; enabled?: boolean | undefined; staleTime?: number | undefined; refetchInterval?: number | false | ((data: Comment[] | undefined, query: Query<...>) => number | false) | undefined; ... 29 more ...; meta?: QueryMeta | undefined; }' is not assignable to parameter of type 'UseQueryOptions<Comment[], unknown, Comment[], string[]>'.
      Types of property 'refetchInterval' are incompatible.
        Type 'number | false | ((data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], QueryKey>) => number | false) | undefined' is not assignable to type 'number | false | ((data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], string[]>) => number | false) | undefined'.
          Type '(data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], QueryKey>) => number | false' is not assignable to type 'number | false | ((data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], string[]>) => number | false) | undefined'.
            Type '(data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], QueryKey>) => number | false' is not assignable to type '(data: Comment[] | undefined, query: Query<Comment[], unknown, Comment[], string[]>) => number | false'.
              Types of parameters 'query' and 'query' are incompatible.
                Type 'Query<Comment[], unknown, Comment[], string[]>' is not assignable to type 'Query<Comment[], unknown, Comment[], QueryKey>'.
                  The types of 'options.queryFn' are incompatible between these types.
                    Type 'QueryFunction<Comment[], string[]> | undefined' is not assignable to type 'QueryFunction<Comment[], QueryKey> | undefined'.
                      Type 'QueryFunction<Comment[], string[]>' is not assignable to type 'QueryFunction<Comment[], QueryKey>'.
                        Type 'QueryKey' is not assignable to type 'string[]'.
                          Type 'string' is not assignable to type 'string[]'.
  Overload 2 of 3, '(queryKey: QueryKey, options?: Omit<UseQueryOptions<unknown, unknown, unknown, QueryKey>, "queryKey"> | undefined): UseQueryResult<unknown, unknown>', gave the following error.
    Argument of type '{ queryKey: string[]; queryFn: () => Promise<Comment[]>; enabled?: boolean | undefined; staleTime?: number | undefined; refetchInterval?: number | false | ((data: Comment[] | undefined, query: Query<...>) => number | false) | undefined; ... 29 more ...; meta?: QueryMeta | undefined; }' is not assignable to parameter of type 'QueryKey'.
      Object literal may only specify known properties, and 'queryKey' does not exist in type 'readonly unknown[]'.  TS2769

    20 | 
    21 | export const useComments = ({ discussionId, config }: UseCommentsOptions) => {
  > 22 |   return useQuery({
       |          ^
    23 |     ...config,
    24 |     queryKey: ['comments', discussionId],
    25 |     queryFn: () => getComments({ discussionId }),

'Helmet' cannot be used as a JSX component.

After cloning and installing dependencies with yarn, I face this error . Is there any way to fix it?

npm version: 8.5.0
node version: v16.14.2

'Helmet' cannot be used as a JSX component.
  Its instance type 'Helmet' is not a valid JSX element.
    The types returned by 'render()' are incompatible between these types.
      Type 'React.ReactNode' is not assignable to type 'import("/Users/sayinmehmet47/Desktop/projeler\u2705/bulletproof-react/node_modules/@testing-library/react-hooks/node_modules/@types/react/index").ReactNode'.
        Type '{}' is not assignable to type 'ReactNode'.  TS2786

     8 | export const Head = ({ title = '', description = '' }: HeadProps = {}) => {
     9 |   return (
  > 10 |     <Helmet
       |      ^
    11 |       title={title ? `${title} | Bulletproof React` : undefined}
    12 |       defaultTitle="Bulletproof React"
    13 |     >

The difference between components/Elements and components/*.

Hi, thanks for the nice architecture design!
I would like to ask you a question regarding the title๐Ÿค”

I would like to know the difference between
a component placed in components/* and
a component placed in components/Elements/*.

Specifically
Head and Layout are global, so I understand that they are placed outside of Elements, but I feel uncomfortable that Form and Notifications are also placed there.
I would like to know what criteria are used to place them there.

Some Typescript declare cannot easy to understand

Hi, this is a good overview of the real project, but sometimes I can't understand much about TypeScript declare in some files, for example in the https://github.com/alan2207/bulletproof-react/blob/master/src/components/Form/Form.tsx:


type FormProps<TFormValues, Schema> = {
  className?: string;
  onSubmit: SubmitHandler<TFormValues>;
  children: (methods: UseFormReturn<TFormValues>) => React.ReactNode;
  options?: UseFormProps<TFormValues>;
  id?: string;
  schema?: Schema;
};

export const Form = <
  TFormValues extends Record<string, unknown> = Record<string, unknown>,
  Schema extends ZodType<unknown, ZodTypeDef, unknown> = ZodType<unknown, ZodTypeDef, unknown>
>({
  onSubmit,
  children,
  className,
  options,
  id,
  schema,
}: FormProps<TFormValues, Schema>) => {
  const methods = useForm<TFormValues>({ ...options, resolver: schema && zodResolver(schema) });
  return (
    <form>
  • The part
<
 TFormValues extends Record<string, unknown> = Record<string, unknown>,
 Schema extends ZodType<unknown, ZodTypeDef, unknown> = ZodType<unknown, ZodTypeDef, unknown>
>

really confuse me, do we need to understand clearly those declarations? Thanks

Tailwind doesn't go well with hardhat

While I'm developing the NFT marketplace, I installed a hardhat.
console : npx hardhat
After developing, when I tried to compile, an error occurred.
The project doesn't recognize the tailwind module, So I reinstalled the tailwind.
console: npm install tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
yarn add --dev tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
Then it worked well.
However, after that, whenever I installed a new module, my project doesn't recognize tailwind and I had to reinstall tailwind everytime.
I think there is a problem with the Webpack. But I can't find the solution.
How can I handle that trouble?

'Routes' is not exported from 'react-router-dom'

Hi,
I Was looking through the code and trying to implement some of the ideas, but I see that every Route is wrapped in a Routes component e.g:

import { Route, Routes } from 'react-router-dom';

import { Discussion } from './Discussion';
import { Discussions } from './Discussions';

export const DiscussionsRoutes = () => {
  return (
    <Routes>
      <Route path="" element={<Discussions />} />
      <Route path=":discussionId" element={<Discussion />} />
    </Routes>
  );
};

I can't find any info about Routes in react-router docs, and also I cannot import it. I get :

'Routes' is not exported from 'react-router-dom'

Is it a deprecated component? is there an alternative for it? what does it suppose to do?

Thanks!

@/ imports - consider alternatives?

Thank you for this amazing source of practices, I've been sharing it with lot of people!

@/ imports confuses me, could you please add alternatives to the doc? I'm not sure if and why this is a best way.

Another option is to set baseUrl: 'src' to tsconfig and now instead of '@/components/X' we import from 'components/X'. I don't think there are meaningful and maintained 'components', 'hooks', 'lib', 'assets' packages on npm.

Another option is to use relative paths, editors are smart nowadays, they write imports automatically, they update imports automatically when moving files. At least VSCode and JetBrains editors a capable. Most of people are using VSCode, so this shouldn't be a problem.

Project structure: a feature to handle Application boostrap & layout

Hi,
what do you thing about handle Application Bootstrap and Layout as a feature?

When starting an application it is often necessary to extract data from the server and consequently show a loading page. Then when the client get the data the landing page (with its layout) is rendered to the user.

Any suggestion regarding the name of this feature?
This feature could also include things such error pages that you put in misc feature.

What do you think?

Many thanks in advance,
Mauro

Shared/common locales location?

Let's suppose to use react-i18next to manage internationalization, where would you put locales files?

Would you put everything in src/locales or instead give each feature its own locales (and maybe use src/locales for shared ones)?

Many thanks in advance for your reply (your time).

Cheers,
Mauro

getValues in react-hook-form

Hi,
How would you add a getValues watcher in this stack?

The problem is I have a form, with two SelectFields but I only can insert the options of the second SelectField as soon as I know what option is in the first SelectField.

Basically I have two selects where the second one depends on the first one. ๐Ÿ˜„
Thanks!

What is the src/lib directory used for?

I have seen the src/lib directory in many projects but I have no idea why we should use it.

For example, in this project, you put the authorization.tsx file in this directory, it could be in the utils or hooks or even components directory. (I haven't read this project completely and maybe I'm wrong but you get the point.)

Can someone explain to me exactly what files should be placed in it? sometimes even functions and hooks are placed in this directory, when we should do this?

Is something else needed for absolute imports to wrok?

First off thanks for this repo! It's been an incredible resource so far. I'm building a project based on its guidelines at the moment and I'm having an issue setting up the absolute imports as you described in the absolute imports section. When I run the project I get the following below error in the terminal, as well as for any other file that imports something using the @/something syntax. VS code correctly suggests imports using the syntax after updating the tsconfig.json and adding tsconfig.paths.json but I just want to make sure there wasn't any other config that I needed to add to get it working.

The error

ERROR in ./src/features/auth/components/SignInPage.tsx 10:0-41
Module not found: Error: Can't resolve '@/components/Button' in '/Users/nathan/projects/react/merchant-portal/src/features/auth/components'

In SignInPage.tsx I've imported the Button component using

import Button from '@/components/Button';

and the Button component is the default export from the file found at ./src/components/Button.tsx.

tsconfig.paths.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"],
  "exclude": ["node_modules"],
  "extends": "./tsconfig.paths.json"
}

Typings in form wrapper

Does anyone have an idea how to correctly type the src/client/components/Form/Form.tsx


export const Form = <
  TFormValues extends Record<string, any> = Record<string, any>,
  Schema extends ZodType<any, any, any> = ZodType<any, any, any>
>({
  onSubmit,
  children,
  className,
  options,
  id,
  schema,
}: FormProps<TFormValues, Schema>) => {
  const methods = useForm<TFormValues>({
    ...options,
    resolver: schema && zodResolver(schema),
  });

There are quiet some any types which I'd like to get rid off.

Thanks for the help!

Clean installation fails on "yarn install" errors

Following the instructions in https://github.com/alan2207/bulletproof-react/blob/master/docs/application-overview.md I got the following errors in the console log (Mac OSX):

yarn install v1.22.10
[1/4] ๐Ÿ”  Resolving packages...
warning Resolution field "[email protected]" is incompatible with requested version "babel-loader@^8.2.2"
warning Resolution field "[email protected]" is incompatible with requested version "babel-loader@^8.2.2"
warning Resolution field "[email protected]" is incompatible with requested version "babel-loader@^8.2.2"
[2/4] ๐Ÿšš  Fetching packages...
error An unexpected error occurred: "/Users/craigmcc/Library/Caches/Yarn/v6/npm-upper-case-1.1.3-f6b4501c2ec4cdd26ba78be7222961de77621598-integrity/node_modules/upper-case/.yarn-metadata.json: Unexpected end of JSON input".
info If you think this is a bug, please open a bug report with the information provided in "/Users/craigmcc/Git.Examples/bulletproof-react/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

The referenced yarn-error.log file is attached below:
yarn-error.log

The hover effect is broken in the Button component

In the Button component there's this line:

const variants = {
  primary: 'bg-blue-600 text-white hover:bg-gray-50:text-blue-600',
  inverse: 'bg-white text-blue-600 hover:bg-blue-600:text-white',
  danger: 'bg-red-600 text-white hover:bg-red-50:text-red-600',
};

The background and text color classes are being stacked on top of each other on the hover modifier, which I don't think is supported by Tailwind, you can stack modifiers upon each other, but not classes. I believe it should look like this:

    const variants = {
      primary: 'bg-blue-600 text-white hover:bg-gray-50 hover:text-blue-600',
      inverse: 'bg-white text-blue-600 hover:bg-blue-600 hover:text-white',
      danger: 'bg-red-600 text-white hover:bg-red-50 hover:text-red-600',
    };

Indeed, upon inspecting the Button component locally and on the live demo website, the hover effect doesn't seem to be working.

There are other couple minor (non)issues, first in the deleteUser.ts file:

      queryClient.setQueryData(
        'users',
        previousUsers?.filter((discussion) => discussion.id !== deletedUser.userId)
      );

The code is filtering an array of User objects, but the parameter for the filter callback is named discussion which is not semantically correct, something like user should be used instead.

The other thing in the teamsHandlers array in the teams.ts file @ line No.47:

    rest.patch<TeamBody>(`${API_URL}/team/:teamId`, (req, res, ctx) => {

The url has a :teamId parameter, but it is not being utilized anywhere in the code by extracting it with something like req.params, instead the code uses the user.teamId value obtained from the requireAuth(req) function. So it makes sense to eliminate this :itemId parameter all together from the url.

Finally, and this is a mere suggestion, in the Table component @ line 47:

   <tr
       key={entry?.id || entryIndex}
       className={entryIndex % 2 === 0 ? 'bg-white' : 'bg-gray-100'}
   >

I think this would be a good place to make use of Tailwind's odd and even modifiers:

  <tr
      key={entry?.id || entryIndex}
      className='odd:bg-white even:bg-gray-100'
  >

Circular dependency when importing types from other features

Discussed in https://github.com/alan2207/bulletproof-react/discussions/39

Originally posted by SevenOutman October 9, 2021
It's a common scenario when we import type definitions from other features, especially definitions for resources (fetched from APIs). If we expose everything from only the index.ts to other features, it's easy to encounter circular dependency.

For example, if I'm writing a components in teams feature where type User from users feature is used:

// teams/components/MyComponent.ts
import type { User } from '@/features/users';

That will cause components from users to also be loaded because I re-exported them from users/index.ts.

// users/index.ts
export * from './types';
export * from './components';

Meanwhile I have a component in users feature that imports type Team from teams feature:

// users/component/MyComponent.ts
import type { Team } from '@/features/teams';

Now my teams/components/MyComponent.ts and users/component/MyComponent.ts forms a circular dependency.

My solution is to import types from other features directly from their ./types.ts, which means that ./index.ts is not reguarded as the only port of a feature.

Same problem exists with importing APIs from other features. Any idea?

How can I implement bulletproof-react with MUI ?

Hi, I'm a very newbie to React and I'd like to refer to this wonderful template.

How can I implement this template with MUI ?

I understand this question is a very basic and general question. So I'm wondering if this is an inappropriate issue.
For instance, when I'd like to use MUI's TextField, should I change the code in the elements/Form/ codes ?
And if so, do you have some examples ?
Definitely I don't understand some important contents about React and so on.
Sorry if this is a very off-topic question.

Ejecting the webpack

Hello,

are you guys planning to eject webpack? Now this boilerplate webpack is depend on react-scripts.

Thanks.

Project structure: specializing stores directory

In React there are many ways to handle state.
I personally use redux (via redux toolkit), context and also state at component level (useState).

What do you think about specializing the stores directory creating as many subfolders as necessary (eg. redux, contexts, recoil, jotai, ...)?

Many thanks in advance.

Mauro

Where should tests be located?

Looking at the project structure

I quickly glanced and saw there was a test directory but it seems to be only for

+-- test              # test utilities and mock server

When navigating to the test folder in this repo I see its mainly support files.

Looking around I can see some directories have a __tests__ directory within the components/XXX directory. Whilst some do not


Is having a __tests__ directory the recommended approach then?

Currently we're split between using two different approaches for where to store our tests:

  1. projectRoot/tests
  2. Place the corresponding *.test.tsx file for next to the component in src

The problem with 1. is that depending on how large the codebase is, it can be hard to find the corresponding test.
The problem with 2. is that it quickly clutters any directory as the number of files quickly doubles since each component now has a test file.

Nextjs version

It will be awesome if we have bulletproof-nextjs what do you think ๐Ÿ˜†

Project structure: the routes folder

Could you please explain what to put under routes folder?
Do I have to put the mapping Component <=> Url or the components using react-router?

Many thanks in advance for your help.

Mauro

Can You provide same sturcuture for JS ?

It seems to be a bit difficult to understand this structure, can you provide or suggest any simple structure for a kick start a new project.

Or Can you publish the same structure for JS instead of TS ?

Is it necessary to put Api call inside the page (feature) folder or can we make some global service folder where we create API call?

Form.tsx typings

NOTE: I'm still learning Typescript, and weeks after posting this, I learned that the type after = sign is the default type.

I know this question is Typescript-specific, but I can't find articles about it.

Why do you do this in the Form.tsx?
TFormValues extends Record<string, unknown> = Record<string, unknown>

Is it really different from this?
TFormValues extends Record<string, unknown>

Table cell type error

I'm getting the following error on the table component.

ERROR in src/components/Elements/Table/Table.tsx:57:25 TS2322: Type 'Element | Entry[keyof Entry]' is not assignable to type 'ReactNode'. Type 'Entry[keyof Entry]' is not assignable to type 'ReactNode'. Type 'Entry[string] | Entry[number] | Entry[symbol]' is not assignable to type 'ReactNode'. Type 'Entry[string]' is not assignable to type 'ReactNode'. Type 'Entry[string]' is not assignable to type 'ReactPortal'. Type 'Entry[keyof Entry]' is not assignable to type 'ReactPortal'. Type 'Entry[string] | Entry[number] | Entry[symbol]' is not assignable to type 'ReactPortal'. Type 'Entry[string]' is not assignable to type 'ReactPortal'.

I presume there is a problem with the TableColumn type definition.

type TableColumn<Entry> = { title: string; field: keyof Entry; Cell?({ entry }: { entry: Entry }): React.ReactElement; };

I'm only just learning TS and haven't been able to figure out what the Cell type definition is doing. An explanation on this would be greatly appreciated!

How to use react-hook-form's setValue etc

Hi ! I'm learning from this wonderful repository.

I would like to ask that can I use react-hook-form's setValue etc.

In this repo's Form structure, how to use setValue etc from other components.

I think that this repo's form structure offers really reusable error handling and labeling.
On the other hand, I don't find appropriate way to set values dynamically on this form structure.
I envision a form that automatically populates the next form with values based on the input values.

For instance, I tried the code like below:

<Form<UserValues typeof schema>
  ...
 >
    {({ formState, control, setValue, watch }) => (
       ....
    )}
</Form>

And below is my sample input field.

import { Controller, UseFormRegisterReturn } from 'react-hook-form';
import TextField from '@mui/material/TextField';

import { FieldWrapper, FieldWrapperPassThroughProps } from './FieldWrapper';

type InputFieldProps = FieldWrapperPassThroughProps & {
  type?: 'text' | 'email' | 'password';
  onChange?: any;
  defaultValue?: string;
  control: any;
  setValue?: any;
  name: string;
};

export const InputField = (props: InputFieldProps) => {
  const { type = 'text', label, onChange, defaultValue, control, setValue, name, error } = props;

  return (
      <FieldWrapper label={label} error={error}>
        <Controller
          name={name}
          control={control}
          defaultValue={defaultValue}
          render={({ field, fieldState, formState }) => {
            return (
              <TextField
                label={label}
                type={type}
                value={field.value}
                ref={field.ref}
                onChange={onChange}
              />
            );
          }}
        />
      </FieldWrapper>
    );
  };

I use MUI for input components, so I use a control variable and it is used for Controller in the component.
I can get setValue, watch and something, but I don't understand how to use these variables.

I understand this is very general and not critical question.

I would really appreciate it if you could answer my question.

Thanks.

Backend for this repo

Hi thanks for this repository. Is there a back-end for this. Like I wanted to run the application locally, but cannot proceed beyond login/signup for obvious reason.

Not sure if I missed any documentation on how to achieve this.

PromiseValue from 'type-fest' library was removed

PromiseValue used in 'src/lib/react-query.ts' from 'type-fest' library was removed as its deprecated in favor of Awaited keyword in typescript 4.5. Pls upgrade typescript version to the latest.

@typescript-eslint/no-floating-promises

I find the lint rule @typescript-eslint/no-floating-promises very valuable and allowing to catch bugs early, I would find it useful to add it to the default eslint conf, wdyt?

Incorrect link for Code splitting example

In the file docs/performance.md there is a link for "Code Splitting Example Code", which currently redirects to src/routes/index.tsx, but there are no code splitting examples. I think it should redirect to src/routes/protected.tsx

ESLint "no-restricted-imports" rule

Hi,
I have a question about the ESLint rule proposed in Project Structure, which is the following:

{
    rules: {
        'no-restricted-imports': [
            'error',
            {
                patterns: ['@/features/*/*'],
            },
        ],

    // ...rest of the configuration
}

This rule aims to limit the import statements to the index file only, using it as the public API of the feature.
This is great, but it is limiting when implementing the feature: if the feature has a complex structure, it is convenient to be able to use absolute imports for its implementation.

Example:

src/features/awesome-feature
|
+-- api
|
+-- components/complex/structure/that/want/to/access/api/Example.jsx
|
...

In Example.jsx it would be better to use

import { query } from "@/features/awesome-feature/api/queries";

instead of

import { query } from "../../../../../../../api/queries";

Is it possible to refine the rule somewhat, so that it allows absolute imports for such use case?

Many thanks,
Mauro

npm install requires --force due to peer depencies

Hey, I cloned master and went to npm install...

But I got this message because of react-scripts and @reach/router peer dependencies:

C:\dev\bulletproof-react (master -> origin)
ฮป npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: [email protected]
npm ERR! node_modules/react
npm ERR!   react@"^17.0.2" from the root project
npm ERR!   peer react@">= 16" from [email protected]
npm ERR!   node_modules/react-scripts
npm ERR!     react-scripts@"4.0.3" from the root project
npm ERR!     peer react-scripts@"^4.0.0" from @craco/[email protected]
npm ERR!     node_modules/@craco/craco
npm ERR!       @craco/craco@"^6.1.2" from the root project
npm ERR!     1 more (@storybook/preset-create-react-app)
npm ERR!   36 more (@headlessui/react, @heroicons/react, react-hook-form, ...)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"15.x || 16.x || 16.4.0-alpha.0911da3" from @reach/[email protected]
npm ERR! node_modules/@storybook/api/node_modules/@reach/router
npm ERR!   @reach/router@"^1.3.4" from @storybook/[email protected]
npm ERR!   node_modules/@storybook/api
npm ERR!     @storybook/api@"6.3.2" from @storybook/[email protected]
npm ERR!     node_modules/@storybook/addon-actions
npm ERR!       dev @storybook/addon-actions@"^6.3.2" from the root project
npm ERR!       1 more (@storybook/addon-essentials)
npm ERR!     10 more (@storybook/addon-essentials, @storybook/addons, ...)
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Maybe there are newer versions of those dependencies?

IDK why it's taken some packages a long time to add the line "|| ^17" to their package.json files, because this is still a common problem despite no breaking changes in React 17.

Notification transition not working

The notification popups are not triggering their transition, they just instantly appears and disappears.

Do you have any idea what might be the issue?
Tried on macOS Monterey and Windows 10
Chrome and Safari

I managed to do a workaround like this (not the prettiest, but it works)

Notification.tsx

 const [show, setShow] = React.useState(false);

  React.useEffect(() => {
    setTimeout(() => {
      setShow(true);
    }, 50);
  }, []);

      <Transition
          show={show}
          /*...*/
        >
...

<button                
onClick={() => {
      setShow(false);
      setTimeout(() => {
        onDismiss(id);
      }, 100);
    }}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.