Repository: manjula91/react-advanced-patterns
Branch: master
Commit: b61548223832
Files: 14
Total size: 28.6 KB
Directory structure:
gitextract_u1enx8_q/
├── .all-contributorsrc
├── .gitignore
├── README.md
├── compound-components/
│ └── README.md
├── flexible-compound-components/
│ └── README.md
├── hoc/
│ └── README.md
├── hooks/
│ └── README.md
├── package.json
├── prop-collection/
│ └── README.md
├── prop-getters/
│ └── README.md
├── provider-pattern/
│ └── README.md
├── react-best-practices/
│ └── README.md
├── render-props/
│ └── README.md
└── state-reducers/
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .all-contributorsrc
================================================
{
"projectName": "react-advanced-patterns",
"projectOwner": "manjula91",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": true,
"contributors": [
{
"login": "manjula91",
"name": "Manjula Subhashchandra Dube",
"avatar_url": "https://avatars0.githubusercontent.com/u/7845921?v=4",
"profile": "https://www.linkedin.com/profile/view?id=181968473&trk=nav_responsive_tab_profile",
"contributions": [
"doc",
"code",
"example"
]
},
{
"login": "vivek12345",
"name": "Vivek Nayyar",
"avatar_url": "https://avatars3.githubusercontent.com/u/4931048?v=4",
"profile": "https://www.viveknayyar.in/",
"contributions": [
"doc",
"code",
"example"
]
},
{
"login": "ryands17",
"name": "Ryan Dsouza",
"avatar_url": "https://avatars2.githubusercontent.com/u/19697099?v=4",
"profile": "https://github.com/ryands17",
"contributions": [
"doc",
"example"
]
},
{
"login": "meghna-saxena",
"name": "Meghna Srivastava",
"avatar_url": "https://avatars3.githubusercontent.com/u/18181755?v=4",
"profile": "https://meghnasrivastava.herokuapp.com",
"contributions": [
"doc",
"example"
]
},
{
"login": "EdwardDrapkin",
"name": "Edward Drapkin",
"avatar_url": "https://avatars1.githubusercontent.com/u/6296006?v=4",
"profile": "https://github.com/EdwardDrapkin",
"contributions": [
"doc",
"example"
]
},
{
"login": "felipediogo",
"name": "Felipe F. Diogo",
"avatar_url": "https://avatars3.githubusercontent.com/u/26486135?v=4",
"profile": "https://github.com/felipediogo",
"contributions": [
"doc",
"example"
]
},
{
"login": "alexrohleder",
"name": "Alex Rohleder",
"avatar_url": "https://avatars2.githubusercontent.com/u/7248028?v=4",
"profile": "https://www.alexrohleder.com",
"contributions": [
"doc",
"example"
]
},
{
"login": "5achinJani",
"name": "Sachin Jani",
"avatar_url": "https://avatars3.githubusercontent.com/u/23077544?v=4",
"profile": "https://twitter.com/5achinJani",
"contributions": [
"doc",
"example"
]
},
{
"login": "garetmckinley",
"name": "Garet McKinley",
"avatar_url": "https://avatars0.githubusercontent.com/u/1624279?v=4",
"profile": "https://garet.io",
"contributions": [
"doc",
"example"
]
},
{
"login": "kuldeepkeshwar",
"name": "anotherjsguy",
"avatar_url": "https://avatars1.githubusercontent.com/u/10448534?v=4",
"profile": "https://in.linkedin.com/in/kuldeepkeshwar",
"contributions": [
"doc",
"example"
]
}
]
}
================================================
FILE: .gitignore
================================================
node_modules
================================================
FILE: README.md
================================================
# <h1 align="center">React Advanced Patterns </h1>
[](#contributors)
<p> This repo is maintained to have collection of react patterns & best practices used in the community. This repo provides you the collated list of all the patterns used in the community. If You have discovered one & would love to share your own react pattern simply send us a PR 🙌 </p>
This is highly inspired from [Michael Jackson](https://github.com/mjackson) & [Kent C. Dodds.](https://twitter.com/kentcdodds) So special thanks to them for the lovely react patterns in life 😊
#### React Advanced Patterns
- [Compound Components](https://github.com/manjula91/react-advanced-patterns/tree/master/compound-components)
- [Flexible Compound Components](https://github.com/manjula91/react-advanced-patterns/tree/master/flexible-compound-components)
- [Prop Collection](https://github.com/manjula91/react-advanced-patterns/tree/master/prop-collection)
- [Prop Getters](https://github.com/manjula91/react-advanced-patterns/tree/master/prop-getters)
- [Render Props](https://github.com/manjula91/react-advanced-patterns/tree/master/render-props)
- [State Reducers](https://github.com/manjula91/react-advanced-patterns/tree/master/state-reducers)
- [Higher Order Components](https://github.com/manjula91/react-advanced-patterns/tree/master/hoc)
- [Provider Pattern](https://github.com/manjula91/react-advanced-patterns/tree/master/provider-pattern)
- [React Hooks](https://github.com/manjula91/react-advanced-patterns/tree/master/hooks)
#### Best Practices when you React
- [Functional setState](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#function-in-setstate)
- [Get Rid of Unnecessary updates in React](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#why-did-you-update)
- [Destructuring and spreading props](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#prop-spread)
- [Runtime type checking with prop types](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#prop-types)
- [Using defaultProps](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#default-props)
- [Using displayName](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#display-name)
- [Conditional Rendering](https://github.com/manjula91/react-advanced-patterns/tree/master/react-best-practices/#conditional-rendering)
If you want to propose a pattern you should submit it with below points:
- What is so special about this pattern?
- Use case or inspired from ?
- Example ([CodesandBox](https://codesandbox.io/) preferred)
## Contributors
Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
| [<img src="https://avatars0.githubusercontent.com/u/7845921?v=4" width="100px;"/><br /><sub><b>Manjula Subhashchandra Dube</b></sub>](https://www.linkedin.com/profile/view?id=181968473&trk=nav_responsive_tab_profile)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=manjula91 "Documentation") [💻](https://github.com/manjula91/react-advanced-patterns/commits?author=manjula91 "Code") [💡](#example-manjula91 "Examples") | [<img src="https://avatars3.githubusercontent.com/u/4931048?v=4" width="100px;"/><br /><sub><b>Vivek Nayyar</b></sub>](https://www.viveknayyar.in/)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=vivek12345 "Documentation") [💻](https://github.com/manjula91/react-advanced-patterns/commits?author=vivek12345 "Code") [💡](#example-vivek12345 "Examples") | [<img src="https://avatars2.githubusercontent.com/u/19697099?v=4" width="100px;"/><br /><sub><b>Ryan Dsouza</b></sub>](https://github.com/ryands17)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=ryands17 "Documentation") [💡](#example-ryands17 "Examples") | [<img src="https://avatars3.githubusercontent.com/u/18181755?v=4" width="100px;"/><br /><sub><b>Meghna Srivastava</b></sub>](https://meghnasrivastava.herokuapp.com)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=meghna-saxena "Documentation") [💡](#example-meghna-saxena "Examples") | [<img src="https://avatars1.githubusercontent.com/u/6296006?v=4" width="100px;"/><br /><sub><b>Edward Drapkin</b></sub>](https://github.com/EdwardDrapkin)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=EdwardDrapkin "Documentation") [💡](#example-EdwardDrapkin "Examples") | [<img src="https://avatars3.githubusercontent.com/u/26486135?v=4" width="100px;"/><br /><sub><b>Felipe F. Diogo</b></sub>](https://github.com/felipediogo)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=felipediogo "Documentation") [💡](#example-felipediogo "Examples") | [<img src="https://avatars2.githubusercontent.com/u/7248028?v=4" width="100px;"/><br /><sub><b>Alex Rohleder</b></sub>](https://www.alexrohleder.com)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=alexrohleder "Documentation") [💡](#example-alexrohleder "Examples") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars3.githubusercontent.com/u/23077544?v=4" width="100px;"/><br /><sub><b>Sachin Jani</b></sub>](https://twitter.com/5achinJani)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=5achinJani "Documentation") [💡](#example-5achinJani "Examples") | [<img src="https://avatars0.githubusercontent.com/u/1624279?v=4" width="100px;"/><br /><sub><b>Garet McKinley</b></sub>](https://garet.io)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=garetmckinley "Documentation") [💡](#example-garetmckinley "Examples") | [<img src="https://avatars1.githubusercontent.com/u/10448534?v=4" width="100px;"/><br /><sub><b>anotherjsguy</b></sub>](https://in.linkedin.com/in/kuldeepkeshwar)<br />[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=kuldeepkeshwar "Documentation") [💡](#example-kuldeepkeshwar "Examples") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
================================================
FILE: compound-components/README.md
================================================
# Compound Components
### What are Compound Components?
Compound Component is a pattern in React where a component doesn't work by itself and needs other specific components to be its children or parents in order to operate. But they still have the control to do lot of stuff on them :)
It is a pattern in which components are used together such that they share an implicit state that let’s them communicate with each other in the background.
> Think of compound components like the ```<select>``` and ```<option>``` elements in HTML. Apart they don't do too much, but together they allow you to create the complete experience — [Kent C. Dodds.](https://twitter.com/kentcdodds)
### What is so special about this pattern
Compound Component allows us as a developer to have a full control over the rendering behavior, that gives us, ability to decide in what order the component should render.
Compound Component also reduces the tension of passing tons & tons of configuration as a prop.
Take a look at the documentation for semantic-ui-react, their Form component is all about Compound Component.
```jsx
import { Form } from 'semantic-ui-react'
const Usage = () => (
<Form>
<Form.Group>
<Form.Input />
<Form.Select />
<Form.Button />
</Form.Group>
</Form>
)
```
### Code Sandbox Example
Below is an example of grouping the RadioButton highly inspired by [semantic-ui-react](https://react.semantic-ui.com/collections/form/)
[Grouping the radio buttons](https://codesandbox.io/s/z32mw29474)
================================================
FILE: flexible-compound-components/README.md
================================================
# Flexible Compound Components
What are Flexible Compound Components?
* This is better version of compound components which makes use of context API and compound component together. This will work even if your order of component changes (which is quite often). This will basically allow user to have more flexibility by using React context to share the implicit state to our child components. We will start with defining childContextTypes, providing the value with getChildContext, and, on each of the components that need that context, we define contextTypes so that React will pass the context that is being asked for. This is more flexible than just using compound components. The consumer component are basically designed in a way that they use render prop in order to work.
### Example
This is an example of grouping the RadioButton highly inspired by [semantic-ui-react](https://react.semantic-ui.com/collections/form/).
[Grouping the radio buttons](https://codesandbox.io/s/z304lk196l)
================================================
FILE: hoc/README.md
================================================
# Higher Order Components
### What are Higher Order Components
Higher order components are a pattern in which a function accepts a component and returns an enhanced version of the component by injecting the required props.
### What is so special about this pattern
HOC's are a pattern used a lot. The most common being the `connect` method of `react-redux` or `withRouter` of `react-router-dom`. This pattern wraps the given Component and returns the same component just by adding extra props to it. This type of function should be pure as it cannot modify the original component, just enhance it.
The drawback to HOC's is prop-collision. A component wrapped with two or more higher order methods could have props of the same name and any one of those could be overriden. This is where render-props comes to the rescue.
For prop-collision, lets take the same example as the one in the example section. What if instead of one set of data, I have to render two sets of data, which means I need two fetch hoc's.
The code will be something like this -
```jsx
let App = fetchHOC({ url: 'my-url-1' })(App)
App = fetchHOC({ url: 'my-url-2' })(App)
```
The data prop being the same will cause just one set of data to be displayed, which is incorrect. Now take a look at the render-prop example and see for yourself that this case can be easily handled.
### Example
This example demonstrates how we can use the Fetch API as a higher order component.
[Fetch using HOC](https://codesandbox.io/s/734060mlm6)
================================================
FILE: hooks/README.md
================================================
# Hooks
### What are hooks ?
Hooks are a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha and being discussed in an open RFC.
### What is so special about hooks?
With Hooks, you can extract stateful logic from a component so it can be tested independently and reused. Hooks allow you to reuse stateful logic without changing your component hierarchy. This makes it easy to share Hooks among many components or with the community.
An example of this can be the useState hook. With this hook you no-longer would need a class component to maintain state.
A functional component with useState hook can maintain state and also perform some side-effects like data-fetching using another well known hook called as useEffect
```jsx
import { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
```
To read more about hooks, refer to this [link](https://reactjs.org/docs/hooks-intro.html
)
Article [link](https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889) written by Dan Abramov
### Example
Here's the codesanbox
[useState](https://codesandbox.io/s/l7407qjzjm)
[useEffect and useReducer](https://codesandbox.io/s/6x41m44wqz)
### Community created hooks
[react-use](https://github.com/streamich/react-use)
[the-platform](https://github.com/palmerhq/the-platform)
[react-hanger](https://github.com/kitze/react-hanger)
================================================
FILE: package.json
================================================
{
"name": "react-advanced-patterns",
"version": "1.0.0",
"description": "Repo containing some advanced patterns for react and for writing better React applications",
"main": "index.js",
"repository": "https://github.com/manjula91/react-advanced-patterns.git",
"author": "Manjula Dube",
"license": "MIT",
"devDependencies": {
"all-contributors-cli": "^5.4.1"
},
"scripts": {
"contributors:add": "all-contributors add",
"contributors:generate": "all-contributors generate"
}
}
================================================
FILE: prop-collection/README.md
================================================
# Prop Collections
### What are prop collection?
Prop Collection is a pattern where we can access props from the parent component by passing a single object of props.
### What is so special about this pattern?
This pattern allows us to spread the entire props required on the required component that is passed from the parent.
This ensures that the component receives all the props and we can also add our own props or override the current props.
```jsx
getInputProps = {
type: "text",
onChange: this.onChange
};
<input name="name" {...getInputProps} />
<input name="age" {...getInputProps} />
```
I would prefer using Prop Getters to be more flexible since Prop Collection passes object instead of function which is not very flexible. Also there is a disadvantage for prop collection pattern: as we would need to pass the value externally. There is no way we can send it via props. So for eg you would also have to pass the event handler explicitly. Also if you want to add your own event handler along with the one provided by the parent, you need to extract the method from the parent and combine with your own handler which becomes rather messy.
### Example
Here's the codesanbox [example](https://codesandbox.io/s/yrjmqol7j) for prop collection
================================================
FILE: prop-getters/README.md
================================================
# Prop Getters
### What are prop getters
Prop getters is a very unique pattern. This pattern involves the usage of spreading a function call in which we add our custom props and these are merged with the default props provided by the component.
### What is so special about this pattern ?
Prop getters is a flexible pattern to provide props to the required component. This pattern is great when we want to add our own props without overriding the ones give by the main component.
Suppose we have an input and we spread the props we obtained from the parent component like this:
```jsx
<input {...inputProps} />
```
Now these props we obtained include an onChange method for the input. What if we want to implement our own onChange method?
There is a way but it is messy
```jsx
const {onChange, ...rest} = inputProps
<input
{...rest}
onChange={() => {
onChange()
myOnChangeMethod()
}}
/>
```
A better solution is to provide our method using prop-getters
```jsx
<input
{...getInputProps({
onChange: myOnChangeMethod
})}
/>
```
Now it's upto the main parent component to provide a mechanism to call both the internal and supplied method.
Easy!!!
### Example
Below is an example shows how a Form component can manage state using prop-getters
[Prop Getters in action](https://codesandbox.io/s/2pq87v9r4r)
================================================
FILE: provider-pattern/README.md
================================================
# Provider Pattern
### What is the Provider Pattern
Provider pattern is pattern where we can share data between multiple components. The main Component is responsible for data and state changes (Provider) and the child components receive the data via a special component (Consumer).
### What is so special about this pattern
The best way to create this pattern is using React's new Context API. A method `createContext` is exposed by React from which you can create a Provider and a Consumer.
The problem is that when we want to pass data to components nested deep, we need to pass the props to each and every nested component, which becomes hard to refactor. The term coined for this is called **prop-drilling** (most probably by [Kent C. Dodds](https://twitter.com/kentcdodds)).
The Provider pattern solves this problem. In whichever component you want to access the data, just wrap it by the `Consumer` component which exposes all the state and methods via a render prop (yay!). This ensures that data stays where it is really required.
### Example
This example shows a simple form component made using React's Context API.
[Provider Pattern](https://codesandbox.io/s/p524z98zvx)
================================================
FILE: react-best-practices/README.md
================================================
# <h1 id="function-in-setstate">Function in `setState` 🙌 ❤️</h1>
This is not a pattern but infact a best practice when interacting with your `state` in React.
Instead of passing an object to `setState()`, pass a function instead. The function will be called with the current state of the component, even if the component itself has not been updated yet. The React Reconciler may merge concurrent state updates into a single lifecycle, which can create subtle and hard to find bugs in your code. In the case of a counter, a call like `this.setState({counter: this.state.counter++})` that happens on a user interaction may get fired 5 or 10 times before a React lifecycle occurs, which will lead to stale values in `this.state.counter`. **Values in this.state are not updated until React renders your component** and passing a function to `setState()` (e.g. `this.setState(state => ({counter: state.counter+1}))` will ensure your state is updated with the latest value instead of the latest _rendered_ value.
Further reading in [React's issue tracker](https://github.com/facebook/react/issues/11527)
# <h1 id="why-did-you-update"> Get rid of unnecessary updates in React</h1>
If you want to get rid of unnecessary rerenders and updates in React. Try [why-did-you-update](https://github.com/maicki/why-did-you-update)
Usage:
```
import React from 'react';
if (process.env.NODE_ENV !== 'production') {
const {whyDidYouUpdate} = require('why-did-you-update');
whyDidYouUpdate(React);
}
```
This library is available on npm, install it with: ```npm install --save why-did-you-update``` or ```yarn add why-did-you-update```.
Why did you update is a function that monkey patches React and notifies you in the console when potentially unnecessary re-renders occur.
Here's the [example](https://codesandbox.io/s/jnrx7j30vy)
In the example if you change your component.js to the below code. It will avoid unnecessary re-renders.That is, the component only needs to re-render when its props change. React has a special type of component built-in called PureComponent that is meant for exactly this use case.
Instead of inheriting from React.Component, use React.PureComponent like this:
```
class C extends React.PureComponent {
render() {
return <div>Age: {this.props.age}</div>
}
}
```
# <h1 id="prop-spread">Destructuring and spreading props</h1>
The ESNext Javascript has some great features and this is one of them. While passing props to a child component, we can spread the entire props we need to pass instead of passing them individually.
Instead of this
```jsx
const props = { a: 1, b: 2 }
<MyComponent a={props.a} b={props.b} />
```
We can do this
```jsx
<MyComponent {...props} />
```
Much simpler and easier to read.
This pattern is also helpful if you want to exclude a single prop while passing the rest of them.
```jsx
const props = { a: 1, b: 2, c: 3, d: 4 }
const {a, ...rest} = props
<MyComponent {...rest} />
```
Now this component in render can destructure the props in this manner.
```jsx
class MyComponent extends React.Component {
render() {
const { a, b } = this.props
return (
// JSX
)
}
}
```
# <h1 id="prop-types">Runtime type checking with prop types</h1>
Prop types are very important for checking the validity of props being passed to the component. Prop types help in determining whether the all the props have been passed correctly along with their data types at runtime. This helps identify issues in your component as well as you get prop information just by looking at the component file.
Prop types can be accessed by installing a package `prop-types`.
```jsx
import React from 'react'
import PropTypes from 'prop-types'
class MyCompnent extends React.Component {
render() {
const { prop1, prop2 } = this.props
return (
<div>
<p>Prop 1: {prop1}</p>
<p>Prop 2: {prop2}</p>
</div>
)
}
}
MyComponent.propTypes = {
prop1: PropTypes.string,
prop2: PropTypes.string.isRequired
}
```
Here we have mentioned that our component receives two props, both of which are strings and `prop2` is required. If we do not pass `prop2`, we will receive an error in the browser console.
For more details on prop types you can check out this link in the official React documentation
[Typechecking with PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html)
# <h1 id="default-props">Using defaultProps</h1>
Default Props is a very useful feature as we can define props that do not need to be passed explicitly or when the prop has more than one value (enum type) and a single value will always be present regardless.
Default props just like prop-types can be set on any component like this
```jsx
const MyComponent = ({ color }) => (
<div>
<p>Color: {color}</p>
</div>
)
MyComponent.propTypes = {
color: PropTypes.oneOf(['red', 'green', 'blue'])
}
MyComponent.defaultProps = {
color: 'red'
}
```
Now the value of `color` prop will always be **red** whenever you don't pass it explicitly.
# <h1 id="display-name">Using displayName</h1>
Display name is something that we should use when we create components as these are helpful in debugging.
The React DevTools shows the component name in the rendered component tree. This name is usually the name of the class in Class components
For example
```jsx
class MyComponent extends React.Component { ... }
```
Here the component name `MyComponent` will be shown in the devTools. But for functional components defined like this, you should add a displayName for debugging purposes.
```jsx
const MyComponent = props => { ... }
MyComponent.displayName = 'My Component'
```
This method is extremely useful when you are dealing with Higher Order Components because they provide a name that doesn't reflect the component you are wrapping. Instead, you can modify and use the originally provided name to demonstrate that something was wrapped.
```
function connectToStore(storeName, Component) {
const componentName = Component.displayName || Component.name || 'anonymous'; // can't be sure the component is following best practices!
const name = `connectedTo${storeName}(${componentName})`;
const wrapped = () => {
return <Component />;
};
wrapped.displayName = name;
wrapped.name = name;
return wrapped;
}
```
With this example, calling `connectToStore('Authentication', UserDashboard)` will result in a component that appears in Dev Tools as `connectedToAuthentication(UserDashboard)`!
# <h1 id="conditional-rendering">Conditional Rendering</h1>
Also, when you only want to render an element on one condition, instead of doing this…
```jsx
{
isTrue ? <p>True!</p> : <none />
}
```
… use short-circuit evaluation:
```jsx
{
isTrue && <p>True!</p>
}
```
A note to consider, while conditionally rendering based on the length of an array, compare the length conditionally and then render.
For example, if you do this
```jsx
{
myArray.length && <p>True!</p>
}
```
This will render **0**. As 0 is falsy, the condition will short-circuit and because of that 0 will be rendered.
Instead, do this
```jsx
{
myArray.length > 0 && <p>True!</p>
}
```
Or this
```jsx
{
Boolean(myArray.length) && <p>True!</p>
}
```
================================================
FILE: render-props/README.md
================================================
# Render props
### What are render props
Render props are simply props that accept a function.
### What is so special about this pattern
Render props separate logic from the UI. The component that implements the logic doesn't decide how the UI is rendered, which is why I like this pattern a lot. The other reason is how easy it is to make the entire component declarative by just rendering what you need.
We can easily extend the API of our component and access only the logic required for rendering the UI. This makes render props more flexible as compared to Higher Order Components.
Also almost all patterns implemented using HOC's can be easily converted to the Render Prop pattern.
### Example
This is a simple example of how the imperative fetch API can be converted into a declarative one (inspired by Apollo's Query component).
[Fetch using render props](https://codesandbox.io/s/9yzwmkj7kp)
================================================
FILE: state-reducers/README.md
================================================
# State Reducer
### What is a State Reducer
State Reducer is a pattern where you can set the state of the component in a way similar to the reducer function in Redux.
### What is so special about this pattern
State Reducer pattern is pretty similar to the Redux reducer. It takes the previous state along with the current changes to be made in the state and merges them.
The main advantage of this pattern is that we can use the same components we have, without modifying the existing API and add a new way of updating state whilst keeping the UI separate from the logic (because of the widely loved render-props pattern). The reducer method which we write can be re-used in other components as we do not need to manage the state in our component.
This pattern stands out when all you want is to extend you API for state changes and keeping the current functionality untouched.
### Example
This is an example of how a simple Form component can provide a different API altogether for creating a form.
[Forms with State Reducers](https://codesandbox.io/s/9802yr86q4)
Here is another example showing the use of multiple reducers for the state reduer pattern.
[Multiple State Reducers](https://codesandbox.io/s/1o8o2xzm37)
gitextract_u1enx8_q/
├── .all-contributorsrc
├── .gitignore
├── README.md
├── compound-components/
│ └── README.md
├── flexible-compound-components/
│ └── README.md
├── hoc/
│ └── README.md
├── hooks/
│ └── README.md
├── package.json
├── prop-collection/
│ └── README.md
├── prop-getters/
│ └── README.md
├── provider-pattern/
│ └── README.md
├── react-best-practices/
│ └── README.md
├── render-props/
│ └── README.md
└── state-reducers/
└── README.md
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (31K chars).
[
{
"path": ".all-contributorsrc",
"chars": 3010,
"preview": "{\n \"projectName\": \"react-advanced-patterns\",\n \"projectOwner\": \"manjula91\",\n \"repoType\": \"github\",\n \"repoHost\": \"http"
},
{
"path": ".gitignore",
"chars": 12,
"preview": "node_modules"
},
{
"path": "README.md",
"chars": 6495,
"preview": "# <h1 align=\"center\">React Advanced Patterns </h1>\n\n[. The extraction includes 14 files (28.6 KB), approximately 7.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.