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 ================================================ #

React Advanced Patterns

[![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square)](#contributors)

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 🙌

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)): | [
Manjula Subhashchandra Dube](https://www.linkedin.com/profile/view?id=181968473&trk=nav_responsive_tab_profile)
[📖](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") | [
Vivek Nayyar](https://www.viveknayyar.in/)
[📖](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") | [
Ryan Dsouza](https://github.com/ryands17)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=ryands17 "Documentation") [💡](#example-ryands17 "Examples") | [
Meghna Srivastava](https://meghnasrivastava.herokuapp.com)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=meghna-saxena "Documentation") [💡](#example-meghna-saxena "Examples") | [
Edward Drapkin](https://github.com/EdwardDrapkin)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=EdwardDrapkin "Documentation") [💡](#example-EdwardDrapkin "Examples") | [
Felipe F. Diogo](https://github.com/felipediogo)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=felipediogo "Documentation") [💡](#example-felipediogo "Examples") | [
Alex Rohleder](https://www.alexrohleder.com)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=alexrohleder "Documentation") [💡](#example-alexrohleder "Examples") | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | | [
Sachin Jani](https://twitter.com/5achinJani)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=5achinJani "Documentation") [💡](#example-5achinJani "Examples") | [
Garet McKinley](https://garet.io)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=garetmckinley "Documentation") [💡](#example-garetmckinley "Examples") | [
anotherjsguy](https://in.linkedin.com/in/kuldeepkeshwar)
[📖](https://github.com/manjula91/react-advanced-patterns/commits?author=kuldeepkeshwar "Documentation") [💡](#example-kuldeepkeshwar "Examples") | 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 ``` ``` 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 ``` 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 { onChange() myOnChangeMethod() }} /> ``` A better solution is to provide our method using prop-getters ```jsx ``` 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 ================================================ #

Function in `setState` 🙌 ❤️

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) #

Get rid of unnecessary updates in React

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
Age: {this.props.age}
} } ``` #

Destructuring and spreading props

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 } ``` We can do this ```jsx ``` 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 ``` 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 ) } } ``` #

Runtime type checking with prop types

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 (

Prop 1: {prop1}

Prop 2: {prop2}

) } } 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) #

Using defaultProps

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 }) => (

Color: {color}

) 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. #

Using displayName

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 ; }; 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)`! #

Conditional Rendering

Also, when you only want to render an element on one condition, instead of doing this… ```jsx { isTrue ?

True!

: } ``` … use short-circuit evaluation: ```jsx { isTrue &&

True!

} ``` 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 &&

True!

} ``` 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 &&

True!

} ``` Or this ```jsx { Boolean(myArray.length) &&

True!

} ``` ================================================ 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)