# [PLT-29703](https://cloudimperiumgames.atlassian.net/browse/PLT-29703) Training React Patterns
Course : [A Tour of JavaScript & React Patterns](https://frontendmasters.com/courses/tour-js-patterns/)
Github
## Modules
1. Community Patterns
3. Container/Presentation Pattern
4. Higher-Order Component Pattern
5. Render Props Pattern
6. Hooks Pattern
7. Provider Pattern
8. Compound Pattern
## Community Patterns
Developers has shared a set of the most useful design patterns in the industry. Check the community patterns in [patterns.dev](https://www.patterns.dev).
> Design patterns are a fundamental part of software development, as they provide typical solutions to commonly recurring problems in software design. Rather than providing specific pieces of software, design patterns are merely concepts that can be used to handle recurring themes in an optimized way.
>
> **Source**: [Introduction to Design Patterns](https://www.patterns.dev/posts/introduction/)
---
## Container/Presentation Pattern
**Source**: [Container/Presentational Pattern](https://www.patterns.dev/posts/presentational-container-pattern/)
In React, one way to enforce separation of concerns is by using the Container/Presentational pattern. With this pattern, we can separate the view from the application logic.
### Presentational Component
A presentational component receives its data through props. Its primary function is to simply display the data it receives the way we want them to, including styles, without modifying that data.
### Container Component
The primary function of container components is to pass data to presentational components, which they contain. Container components themselves usually don't render any other components besides the presentational components that care about their data. Since they don't render anything themselves, they usually do not contain any styling either.
### Hooks
In many cases, the Container/Presentational pattern can be replaced with React Hooks. The introduction of Hooks made it easy for developers to add statefulness without needing a container component to provide that state.
---
## Higher-Order Component Pattern
**Source**: [HOC Pattern](https://www.patterns.dev/posts/hoc-pattern/)
Within our application, we often want to use the same logic in multiple components. This logic can include applying a certain styling to components, requiring authorization, or adding a global state.
One way of being able to reuse the same logic in multiple components, is by using the higher order component pattern. This pattern allows us to reuse component logic throughout our application.
### HOC Component
A Higher Order Component (HOC) is a component that receives another component. The HOC contains certain logic that we want to apply to the component that we pass as a parameter. After applying that logic, the HOC returns the element with the additional logic.
### Composing
We can also compose multiple Higher Order Components. Let's say that we also want to add functionality that shows a Hovering! text box when the user hovers over the DogImages list.
### Hooks
In some cases, we can replace the HOC pattern with React Hooks.
### General Advice
**Best use-cases for a HOC:**
- The same, uncustomized behavior needs to be used by many components throughout the application.
- The component can work standalone, without the added custom logic.
**Best use-cases for Hooks:**
- The behavior has to be customized for each component that uses it.
- The behavior is not spread throughout the application, only one or a few components use the behavior.
- The behavior adds many properties to the component
---
## Render Props Pattern
**Source**: [Render Props Pattern](https://www.patterns.dev/posts/render-props-pattern/)
### Render Prop
A render prop is a prop on a component, which value is a function that returns a JSX element. The component itself does not render anything besides the render prop. Instead, the component simply calls the render prop, instead of implementing its own rendering logic.
### Children as a function
Besides regular JSX components, we can pass functions as children to React components. This function is available to us through the children prop, which is technically also a render prop.
### Example
```typescript!
function Input(props) {
const [value, setValue] = useState("");
return (
<>
<input
type="text"
value={value}
onChange={e => setValue(e.target.value)}
placeholder="Temp in °C"
/>
{props.render(value)} // Render Prop
/* {props.children(value)} // Function as children */
</>
);
}
export default function App() {
return (
<div className="App">
<h1>☃️ Temperature Converter 🌞</h1>
<Input
render={value => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}
/>
/* Function as children
<Input
{value => (
<>
<Kelvin value={value} />
<Fahrenheit value={value} />
</>
)}
/> */
</div>
);
}
```
:warning: The issues that we tried to solve with render props, have largely been replaced by **React Hooks**. As Hooks changed the way we can add reusability and data sharing to components, they can replace the render props pattern in many cases.
Since we can't add lifecycle methods to a render prop, we can only use it on components that don't need to alter the data they receive.
---
## Hooks Pattern
**Source**: [Hooks Pattern](https://www.patterns.dev/posts/hooks-pattern/)
React 16.8 introduced a new feature called Hooks. Hooks make it possible to use React state and lifecycle methods, without having to use a ES2015 class component.
Although Hooks are not necessarily a design pattern, Hooks play a very important role in your application design. Many traditional design patterns can be replaced by Hooks.
**Further Reading**: [React render props vs. custom Hooks
](https://blog.logrocket.com/react-render-props-vs-custom-hooks/#what-render-props)
**Useful links**:
- [React Hooks Recipes](https://usehooks.com/)
- [streamich/react-use](https://github.com/streamich/react-use)
- [Collection of React Hooks](https://nikgraf.github.io/react-hooks/)
---
## Provider Pattern
**Source**: [Provider Pattern](https://www.patterns.dev/posts/provider-pattern/)
With the Provider Pattern, we can make data available to multiple components. Rather than passing that data down each layer through props, we can wrap all components in a Provider. A Provider is a higher order component provided to us by the Context object. We can create a Context object, using the createContext method that React provides for us.
### Hooks
We can create a hook to provide context to components. Instead of having to import useContext and the Context in each component, we can use a hook that returns the context we need.
```typescript!
function useThemeContext() {
const theme = useContext(ThemeContext);
if (!theme) {
throw new Error("useThemeContext must be used within ThemeProvider");
}
return theme;
}
```
Instead of wrapping the components directly with the ThemeContext.Provider component, we can create a HOC that wraps the component to provide its values. This way, we can separate the context logic from the rendering components, which improves the reusability of the provider.
```typescript!
function ThemeProvider({children}) {
const [theme, setTheme] = useState("dark");
function toggleTheme() {
setTheme(theme === "light" ? "dark" : "light");
}
const providerValue = {
theme: themes[theme],
toggleTheme
};
return (
<ThemeContext.Provider value={providerValue}>
{children}
</ThemeContext.Provider>
);
}
export default function App() {
return (
<div className={`App theme-${theme}`}>
<ThemeProvider>
<Toggle />
<List />
</ThemeProvider>
</div>
);
}
```
---
## Compound Pattern
**Source**: [Understanding React compound components](https://blog.logrocket.com/understanding-react-compound-components/)
Compound components are a pattern in which components are used together such that they share an implicit state that lets them communicate with each other in the background.
In other words, when multiple components work together to have a shared state and handle logic together, they are called compound components.
### How to import the main Compound component only?
```typescript!
export function FlyOut() {}
function Input() {}
function List() {}
FlyOut.Input = Input
FlyOut.List = List
```
**Usage**
```typescript!
import FlyOut from '.fly-out'
function ParentComponent(props) {
return (
<FlyOut>
<FlyOut.Input>
<FlyOut.List>
</FlyOut>
)
}
```
---
## Glossary
| Name | Example | Definition |
| -------- | -------- | -------- |
| | | |