## CSS
These coding rules are taken from the Airbnb React/JSX Style Guide.
### Use CSS modules
With CSS Modules, itβs a guarantee that all the styles for a single component:
1. Live in one place
2. Only apply to that component and nothing else
Plus, any component can have a true dependency, like:
```tsx
import buttons from "./buttons.css";
import padding from "./padding.css";
element.innerHTML = `
`;
```
**This approach is designed to fix the problem of the** ***global scope*** **in CSS (**[**ref**](https://css-tricks.com/css-modules-part-1-need/)**).**
## Factoring
Have a look at the following page(s) :
- [The Twelve-Factor App](https://12factor.net/)
## Naming
- **Extensions**: Use `.tsx` extension for React components.
- **Filename**: Use PascalCase for filenames. E.g., `ReservationCard.jsx`.
- **Reference Naming**: Use PascalCase for React components and camelCase for their instances. eslint: `react/jsx-pascal-case`
```tsx
// π©
import reservationCard from './ReservationCard';
// π
import ReservationCard from './ReservationCard';
// π©
const ReservationItem =
;
// π
const reservationItem =
;
```
- **Component Naming**: Use the filename as the component name. For example, `ReservationCard.jsx` should have a reference name of `ReservationCard`. However, for root components of a directory, use `index.jsx` as the filename and use the directory name as the component name:
```tsx
// π©
import Footer from './Footer/Footer';
// π©
import Footer from './Footer/index';
// π
import Footer from './Footer';
```
- **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)`.
Why? A componentβs `displayName` may be used by developer tools or in error messages, and having a value that clearly expresses this relationship helps people understand what is happening.
```tsx
// π©
export default function withFoo(WrappedComponent) {
return function WithFoo(props) {
return
;
}
}
// π
export default function withFoo(WrappedComponent) {
function WithFoo(props) {
return
;
}
const wrappedComponentName = WrappedComponent.displayName
|| WrappedComponent.name
|| 'Component';
WithFoo.displayName = `withFoo(${wrappedComponentName})`;
return WithFoo;
}
```
## Logging
Client-Side and Server-Side should logs the message through a function for future adaptability.
## National Language Support (NLS)
Every text displayed to the used should be gathered into one file, in order to ease the traduction that we could need in the future.
## React
### Basic Rules
- Only include one React component per file.
- However, multiple [Stateless, or Pure, Components](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions) are allowed per file. eslint: `react/no-multi-comp`.
- Always use TSX syntax.
- Do not use `React.createElement` unless youβre initializing the app from a file that is not TSX.
- `react/forbid-prop-types` will allow `arrays` and `objects` only if it is explicitly noted what `array` and `object` contains, using `arrayOf`, `objectOf`, or `shape`.
### Class vs `React.createClass` vs stateless
- If you have internal state and/or refs, prefer `class extends React.Component` over `React.createClass`. eslint: `react/prefer-es6-class` `react/prefer-stateless-function`
```tsx
// π©
const Listing = React.createClass({
// ...
render() {
return
{this.state.hello}
;
}
});
// π
class Listing extends React.Component {
// ...
render() {
return
{this.state.hello}
;
}
}
```
And if you donβt have state or refs, prefer normal functions (not arrow functions) over classes:
```tsx
// π©
class Listing extends React.Component {
render() {
return
{this.props.hello}
;
}
}
// π© (relying on function name inference is discouraged)
const Listing = ({ hello }) => (
{hello}
);
// π
function Listing({ hello }) {
return
{hello}
;
}
```
### Mixins
- [Do not use mixins](https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html).
> Why? Mixins introduce implicit dependencies, cause name clashes, and cause snowballing complexity. Most use cases for mixins can be accomplished in better ways via components, higher-order components, or utility modules.
### Share Data with Props
To pass data into a component with props, we will try to use as much as possible the [object destructuring synthax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring).
```tsx
// π©
function MyComponent({ name }) {
return
π₯ {name}
;
}
// π
function MyComponent(props) {
return
π₯ {props.name}
;
}
// Both can be used by the same way
```
### [Antipatterns to avoid](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=15)
#### [01:00](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=60s) Big Components
π© A dirty React component : 
π Prefer functional components with React Hooks
π DRY
π Proper naming & props destructuring
π If you use JS add a PropTypes validation layer
π Split into small pieces
`List.js` : 
`Listen.js` : 
Reference : [Refactoring a Complex React Component](https://levelup.gitconnected.com/refactoring-a-complex-react-component-5-best-practices-to-write-efficient-and-readable-components-b0d06f4f22b4)
#### [01:55](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=115s) Nesting Gotcha
π© *Child using the function defined by the parent => bad performance issue*
```tsx
function Parent(){
const[count, setCount] = useState(0);
const handleClick = () => setCount(count+1);
const Child = () => {
return
+
}
}
return (
)
```
π *pass the function in as a prop*
```tsx
const Child = ({onClick}) => {
return
+
}
function Parent(){
const[count, setCount] = useState(0);
const handleClick = () => setCount(count+1);
}
return (
)
```
#### [02:35](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=155s) Failure to memoΓ―se
If your component renders the same result given the same props, you can wrap it in a call to `React.memo` for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.
`React.memo` only checks for prop changes.
```tsx
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
export default React.memo(MyComponent, areEqual);
```
This method only exists as a [**performance optimization**](https://reactjs.org/docs/optimizing-performance.html)**.** Do not rely on it to βpreventβ a render, as this can lead to bugs.
#### [03:15](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=195s) Useless Divs
π© *As JSX need to return only one element, I wrap the two elements into a* `div`
```tsx
function Frag(){
return (
)
}
```
π *As JSX needs to return only one element, I wrap the two elements into a* `>` *or a* `
`
```tsx
function Frag(){
return (
<>
>
)
}
```
#### [03:44](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=224s) Messy Files
React components should be organised by folders, in which one folder contains one React component.
These folders should include at least a structure similar to the following one (here example with *Navbar*) :
```tsx
Navbar
βββ index.tsx
βββ Navbar.module.css
βββ Navbar.spec.ts
βββ Navbar.tsx
```
The`index.tsx` helps to import our component like this :
- `import Navbar from './Navbar';` π
- not like that : `import Navbar from './Navbar/Navbar';` π©
The`index.tsx` includes the following :
```
export { default } from './Navbar';
```
To help, it has been implemented a folder template that can be used with the [vscode folder template extension](https://github.com/Huuums/vscode-folder-templates).
#### [04:40](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=280s) Big Bundles
If a slow initial page load occurs, it may means the app is too big (importing too much stuff), to tackle this trouble we would try to load some module asynchronously.
π *Using* `lazy` *loading and* `Suspense`:
```tsx
const Button = React.lazy(() => import('./Button'));
function Page(){
return (
Loading... }>
);
}
```
#### [05:34](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=334s) Prop Drilling
##### Which state management libraries to use ? [Hooks](https://reactjs.org/docs/hooks-intro.html), [Redux](https://github.com/reduxjs/redux), and [Recoil](https://github.com/facebookexperimental/Recoil) ?
At first, React hooks will be used as the primary state management tool state, especially with `useState`, `useEffect`, and `useReducer`. We can use `useReducer`as follow ([reference](https://www.youtube.com/watch?v=TNhaISOUy6Q&t=478s)) :
```tsx
function reducer(state, action) {
switch(action.type) {
case 'increment' :
return {count: state + 1};
case 'decrement' :
return {count: state - 1};
default:
throw new Error();
}
}
function App() {
const[state, dispatch] = useReducer(reducer, 0);
return(
<>
Count: {state}
dispatch({type: 'decrement'})}>-
dispatch({type: 'increment'})}>+
>
);
}
```
However if we had to choose one, we may think about Recoil, for the following reason :
- It was built and released by engineers from Facebook's team, the React creator.
- It doesn't impose a strict learning curve as Redux and Mobx do.
- it doesn't intend to have so much Redux boilerplate in the codebase.
##### How to pass data among react component siblings ?
- Redux β no
- ContextAPI (`useContext` hook) β parsimoniously, cause it makes you contained component impossible to reuse without having it with the same context (given by the same outside parent component).
- Combination of callback and use of props β yes
#### [06:30](https://www.youtube.com/watch?v=b0IZo2Aho9Y&list=PL0vfts4VzfNgUUEtEjxDVfh4iocVR3qIb&index=14&t=390s) Prop Plowing
Try to use the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) when you can.
Here an example for spread props :
```tsx
const data = {
id: 7
name: "John",
age: 29
}
return (
// // π©
// π
)
```