You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: frontend/react/style-guide.md
+76-99
Original file line number
Diff line number
Diff line change
@@ -37,62 +37,46 @@ src
37
37
└───app
38
38
│ │
39
39
│ └───components
40
-
│ │ └───atoms # Can't be broken down into smaller things
41
-
│ │ | └───Input
42
-
│ │ | └───Text
43
-
│ │ | └───Button
44
-
│ │ | └───etc
45
-
│ │ └───molecules # Two or more atoms
46
-
│ │ | └───FormInput
47
-
│ │ | └───SearchBar
48
-
│ │ | └───Table
49
-
│ │ | └───etc
50
-
│ │ └───organisms # Two or more molecules
51
-
│ │ └───LoginForm
52
-
│ │ └───UserTable
53
-
│ │ └───etc
40
+
│ | └───FormInput
41
+
│ | └───SearchBar
42
+
│ | └───Table
43
+
│ | └───etc
44
+
| |
54
45
│ └───screens
55
46
│ └───MyScreenComponent
56
47
│ └───assets # Screen specific app assets
57
-
│ └───reducer
58
-
│ | actions.js
59
-
│ | reducer.js
60
-
│ | selectors.js
61
-
│ | effects.js
48
+
│ └───context
49
+
| | index.ts
50
+
│ | actions.ts
51
+
│ | reducer.ts
62
52
│ └───components # Screen specific components
63
-
│ | constants.js
64
-
│ | i18n.js
65
-
│ | index.js
66
-
│ | layout.js
53
+
│ | constants.ts
54
+
│ | i18n.ts
55
+
│ | index.tsx
67
56
│ | styles.scss
68
-
│ | utils.js
57
+
│ | utils.ts
69
58
│
70
59
└───assets # General app assets
71
60
└───config
72
-
| api.js
73
-
| i18n.js
61
+
| api.ts
62
+
| i18n.ts
74
63
└───constants
75
-
└───redux
76
-
│ | store.js
77
-
│ └───myReducer
78
-
│ | actions.js
79
-
│ | reducer.js
80
-
│ | selectors.js
81
-
│ | effects.js
82
-
│
83
-
└───propTypes
84
-
│ | Model1.js
85
-
│ │ Model2.js
64
+
└───types # Custom global TypeScript classes
65
+
└───contexts # Global contexts
66
+
│ └───Auth
67
+
│ | index.ts
68
+
| | reducer.ts
69
+
| | actions.ts
86
70
│
87
71
└───scss
88
72
└───services
89
-
│ │ serializers.js
73
+
│ │ serializers.ts
90
74
│ └───Model
91
-
│ | ModelService.js
92
-
│ | serializers.js
75
+
│ | ModelService.ts
76
+
│ | serializers.ts
93
77
│
94
78
└───utils
95
-
│ index.js
79
+
│ index.tsx
96
80
```
97
81
98
82
## Class vs `React.createClass` vs stateless
@@ -175,18 +159,18 @@ src
175
159
176
160
## Naming
177
161
178
-
-**Extensions**: Use `.js` extension for React components.
179
-
-**Filename**: For services use PascalCase. E.g., `ReservationCard.js` or a folder with the service name and `index.js` as filename. For React components, there must be a folder in PascalCase with its name and the component file should be `index.js` (and optionally `layout.js`if you're using [Smart/Dumb components](https://medium.com/@thejasonfile/dumb-components-and-smart-components-e7b33a698d43)
162
+
-**Extensions**: Use `.ts` extension for React components.
163
+
-**Filename**: For services use PascalCase. E.g., `ReservationCard.ts` or a folder with the service name and `index.tsx` as filename. For React components, there must be a folder in PascalCase with its name and the component file should be `index.tsx`
180
164
-**Reference Naming**: Use PascalCase for React components and camelCase for their associated elements. eslint: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md)
181
165
182
166
```jsx
183
167
// bad
184
168
import myService from './MyService';
185
-
import myComponent from './MyComponent';
169
+
import myComponent from './MyComponent/index.tsx';
186
170
187
171
// good
188
-
import MyService from './MyService'; # webpack infers index.js
189
-
import MyComponent from './MyComponent'; # webpack infers index.js
172
+
import MyService from './MyService'; # webpack infers index.tsx
173
+
import MyComponent from './MyComponent'; # webpack infers index.tsx
190
174
191
175
// bad
192
176
const MyComponent = <MyComponent />;
@@ -196,26 +180,17 @@ src
196
180
```
197
181
-**Component Hierarchy**:
198
182
- Component files should be inside folders that match the component's name.
199
-
- Use index.js as the filename of a container component. Use`Container` as the suffix of the component's name.
200
-
- Use layout.js as the filename of a layout component. Only do this if your component is becoming too big, it should be an exception, not a rule.
183
+
- Use index.tsx as the component filename.
201
184
202
185
203
186
```jsx
204
-
// MyComponent/index.js
205
-
import MyComponent from './layout'
187
+
// MyComponent/index.tsx
206
188
207
-
function MyComponentContainer() {
189
+
function MyComponent() {
208
190
// Do smart stuff
209
191
210
192
return <MyComponent />
211
193
}
212
-
213
-
// MyComponent/layout.js
214
-
function MyComponent() {
215
-
return (
216
-
// Some JSX
217
-
)
218
-
}
219
194
```
220
195
221
196
- **Higher-order Component Naming**: Use a composite of the higher-order component's name and the passed-in component's name as the `displayName` on the generated component. For example, the higher-order component `withFoo()`, when passed a component `Bar` should produce a component with a `displayName` of `withFoo(Bar)`.
@@ -270,15 +245,15 @@ src
270
245
271
246
```jsx
272
247
// bad
273
-
/* routes.js */
248
+
/* routes.ts */
274
249
const userListRoute = '/users';
275
250
const itemListRoute = '/items';
276
251
277
252
/* Another file */
278
253
import * as Routes from './routes';
279
254
280
255
// good
281
-
/* routes.js */
256
+
/* routes.ts */
282
257
const Routes = {
283
258
userListRoute: '/users',
284
259
itemListRoute: '/items'
@@ -405,25 +380,20 @@ src
405
380
- Always use object destructuring to explicitly get props variables in the render function of class Components:
- Always use object destructuring to explicitly get props variables in layout Components:
396
+
- Always use object destructuring to explicitly get props variables:
427
397
428
398
```jsx
429
399
// bad
@@ -472,27 +442,40 @@ src
472
442
/>
473
443
```
474
444
475
-
- Avoid passing arrow functions in props when possible. Instead, create a reference to the function and pass that reference.
445
+
- Only use inline arrow functions when the arrow function is simple
446
+
- If the function is complex, define it as a const beforehand. If you are passing it to a child component. you may use `useCallback` for memoization as well.
476
447
477
448
> Why? Passing arrow functions as props in render creates a new function each time the component renders, which is less performant.
0 commit comments