Repository: vasanthk/react-bits Branch: master Commit: 9c89659797f1 Files: 58 Total size: 109.7 KB Directory structure: gitextract_p1p5oxnm/ ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.txt ├── READINGS.md ├── README.md ├── SUMMARY.md ├── anti-patterns/ │ ├── 01.props-in-initial-state.md │ ├── 02.findDOMNode.md │ ├── 03.mixins.md │ ├── 04.setState-in-componentWillMount.md │ ├── 05.mutating-state.md │ ├── 06.using-indexes-as-key.md │ ├── 07.spreading-props-dom.md │ └── README.md ├── book.json ├── coding-style/ │ └── README.md ├── gotchas/ │ ├── 01.pure-render-checks.md │ ├── 02.synthetic-events.md │ └── README.md ├── package.json ├── patterns/ │ ├── 1.conditionals-in-jsx.md │ ├── 10.passing-function-to-setState.md │ ├── 11.decorators.md │ ├── 12.feature-flags-using-redux.md │ ├── 13.component-switch.md │ ├── 14.reaching-into-a-component.md │ ├── 15.list-components.md │ ├── 16.format-text-via-component.md │ ├── 17.react-fragments.md │ ├── 18.share-tracking-logic.md │ ├── 2.async-nature-of-setState.md │ ├── 3.dependency-injection.md │ ├── 4.context-wrapper.md │ ├── 5.event-handlers.md │ ├── 6.flux-pattern.md │ ├── 7.one-way-data-flow.md │ ├── 8.presentational-vs-container.md │ └── 9.third-party-integration.md ├── perf-tips/ │ ├── 01.shouldComponentUpdate-check.md │ ├── 02.pure-component.md │ ├── 03.reselect.md │ └── README.md ├── styling/ │ ├── 01.stateless-ui-components.md │ ├── 02.styles-module.md │ ├── 03.style-functions.md │ ├── 04.using-npm-modules.md │ ├── 05.base-component.md │ ├── 06.layout-component.md │ ├── 07.typography-component.md │ ├── 08.HOC-for-styling.md │ └── README.md └── ux-variations/ ├── 01.composing-variations.md ├── 02.toggle-ui-elements.md ├── 03.HOC-feature-toggles.md ├── 04.HOC-props-proxy.md ├── 05.wrapper-components.md ├── 06.display-order-variations.md └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ _book node_modules ================================================ FILE: CONTRIBUTING.md ================================================ > Your contributions are heartily ♡ welcome. (✿◠‿◠) ================================================ FILE: LICENSE.txt ================================================ Creative Commons Attribution 4.0 International ======================================================================= Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More_considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= Creative Commons Attribution 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part; and b. produce, reproduce, and Share Adapted Material. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material (including in modified form), You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. ================================================ FILE: READINGS.md ================================================ # Related Links - [React in Patterns by krasimir](https://github.com/krasimir/react-in-patterns) - [React Patterns by planningcenter](https://github.com/planningcenter/react-patterns) - [reactpatterns.com](https://github.com/chantastic/reactpatterns.com) - [10 React Mini-patterns](https://hackernoon.com/10-react-mini-patterns-c1da92f068c5) ================================================ FILE: README.md ================================================ # [React Bits](https://vasanthk.gitbooks.io/react-bits) A compilation of React Patterns, techniques, tips and tricks. **Gitbook format**: https://vasanthk.gitbooks.io/react-bits **Github repo**: https://github.com/vasanthk/react-bits > Your contributions are heartily ♡ welcome. (✿◠‿◠) > **Translations by community:** > - 中文版 (Chinese): [react-bits-cn](https://github.com/hateonion/react-bits-CN) > - 한국어 (Korean): [react-bits-ko](https://github.com/rayleighko/react-bits-ko) - Design Patterns and Techniques - [Conditional in JSX](./patterns/1.conditionals-in-jsx.md) - [Async Nature Of setState()](./patterns/2.async-nature-of-setState.md) - [Dependency Injection](./patterns/3.dependency-injection.md) - [Context Wrapper](./patterns/4.context-wrapper.md) - [Event Handlers](./patterns/5.event-handlers.md) - [Flux Pattern](./patterns/6.flux-pattern.md) - [One Way Data Flow](./patterns/7.one-way-data-flow.md) - [Presentational vs Container](./patterns/8.presentational-vs-container.md) - [Third Party Integration](./patterns/9.third-party-integration.md) - [Passing Function To setState()](./patterns/10.passing-function-to-setState.md) - [Decorators](./patterns/11.decorators.md) - [Feature Flags](./patterns/12.feature-flags-using-redux.md) - [Component Switch](./patterns/13.component-switch.md) - [Reaching Into A Component](./patterns/14.reaching-into-a-component.md) - [List Components](./patterns/15.list-components.md) - [Format Text via Component](./patterns/16.format-text-via-component.md) - [React Fragments](./patterns/17.react-fragments.md) - [Share Tracking Logic](./patterns/18.share-tracking-logic.md) - Anti-Patterns - [Introduction](./anti-patterns/README.md) - [Props In Initial State](./anti-patterns/01.props-in-initial-state.md) - [findDOMNode()](./anti-patterns/02.findDOMNode.md) - [Mixins](./anti-patterns/03.mixins.md) - [setState() in componentWillMount()](./anti-patterns/04.setState-in-componentWillMount.md) - [Mutating State](./anti-patterns/05.mutating-state.md) - [Using Indexes as Key](./anti-patterns/06.using-indexes-as-key.md) - [Spreading Props on DOM elements](./anti-patterns/07.spreading-props-dom.md) - Handling UX Variations - [Introduction](./ux-variations/README.md) - [Composing UX Variations](./ux-variations/01.composing-variations.md) - [Toggle UI Elements](./ux-variations/02.toggle-ui-elements.md) - [HOC for Feature Toggles](./ux-variations/03.HOC-feature-toggles.md) - [HOC props proxy](./ux-variations/04.HOC-props-proxy.md) - [Wrapper Components](./ux-variations/05.wrapper-components.md) - [Display Order Variations](./ux-variations/06.display-order-variations.md) - Perf Tips - [Introduction](./perf-tips/README.md) - [shouldComponentUpdate() check](./perf-tips/01.shouldComponentUpdate-check.md) - [Using Pure Components](./perf-tips/02.pure-component.md) - [Using reselect](./perf-tips/03.reselect.md) - Styling - [Introduction](./styling/README.md) - [Stateless UI Components](./styling/01.stateless-ui-components.md) - [Styles Module](./styling/02.styles-module.md) - [Style Functions](./styling/03.style-functions.md) - [NPM Modules](./styling/04.using-npm-modules.md) - [Base Component](./styling/05.base-component.md) - [Layout Component](./styling/06.layout-component.md) - [Typography Component](./styling/07.typography-component.md) - [HOC for Styling](./styling/08.HOC-for-styling.md) - Gotchas - [Introduction](./gotchas/README.md) - [Pure render checks](./gotchas/01.pure-render-checks.md) - [Synthetic Events](./gotchas/02.synthetic-events.md) - [Related Links](./READINGS.md) ================================================ FILE: SUMMARY.md ================================================ # React Bits ✨ React patterns, techniques, tips and tricks ✨ - Design Patterns and Techniques - [Conditional in JSX](./patterns/18.conditionals-in-jsx.md) - [Async Nature Of setState()](./patterns/19.async-nature-of-setState.md) - [Dependency Injection](./patterns/20.dependency-injection.md) - [Context Wrapper](./patterns/21.context-wrapper.md) - [Event Handlers](./patterns/22.event-handlers.md) - [Flux Pattern](./patterns/23.flux-pattern.md) - [One Way Data Flow](./patterns/24.one-way-data-flow.md) - [Presentational vs Container](./patterns/25.presentational-vs-container.md) - [Third Party Integration](./patterns/26.third-party-integration.md) - [Passing Function To setState()](./patterns/27.passing-function-to-setState.md) - [Decorators](./patterns/28.decorators.md) - [Feature Flags](./patterns/29.feature-flags-using-redux.md) - [Component Switch](./patterns/30.component-switch.md) - [Reaching Into A Component](./patterns/31.reaching-into-a-component.md) - [List Components](./patterns/32.list-components.md) - [Format Text via Component](./patterns/33.format-text-via-component.md) - [Share Tracking Logic](./patterns/34.share-tracking-logic.md) - Anti-Patterns - [Introduction](./anti-patterns/README.md) - [Props In Initial State](./anti-patterns/01.props-in-initial-state.md) - [findDOMNode()](./anti-patterns/02.findDOMNode.md) - [Mixins](./anti-patterns/03.mixins.md) - [setState() in componentWillMount()](./anti-patterns/04.setState-in-componentWillMount.md) - [Mutating State](./anti-patterns/05.mutating-state.md) - [Using Indexes as Key](./anti-patterns/06.using-indexes-as-key.md) - [Spreading Props on DOM elements](./anti-patterns/07.spreading-props-dom.md) - Handling UX Variations - [Introduction](./ux-variations/README.md) - [Composing UX Variations](./ux-variations/01.composing-variations.md) - [Toggle UI Elements](./ux-variations/02.toggle-ui-elements.md) - [HOC for Feature Toggles](./ux-variations/03.HOC-feature-toggles.md) - [HOC props proxy](./ux-variations/04.HOC-props-proxy.md) - [Wrapper Components](./ux-variations/05.wrapper-components.md) - [Display Order Variations](./ux-variations/06.display-order-variations.md) - Perf Tips - [Introduction](./perf-tips/README.md) - [shouldComponentUpdate() check](./perf-tips/01.shouldComponentUpdate-check.md) - [Using Pure Components](./perf-tips/02.pure-component.md) - [Using reselect](./perf-tips/03.reselect.md) - Styling - [Introduction](./styling/README.md) - [Stateless UI Components](./styling/01.stateless-ui-components.md) - [Styles Module](./styling/02.styles-module.md) - [Style Functions](./styling/03.style-functions.md) - [npm Modules](./styling/04.using-npm-modules.md) - [Base Component](./styling/05.base-component.md) - [Layout Component](./styling/06.layout-component.md) - [Typography Component](./styling/07.typography-component.md) - [HOC for Styling](./styling/08.HOC-for-styling.md) - Gotchas - [Introduction](./gotchas/README.md) - [Pure render checks](./gotchas/01.pure-render-checks.md) - [Synthetic Events](./gotchas/02.synthetic-events.md) - [Related Links](./READINGS.md) ================================================ FILE: anti-patterns/01.props-in-initial-state.md ================================================ # Props in Initial State From docs: > Using props to generate state in getInitialState often leads to duplication of “source of truth”, i.e. where the real data is. > This is because getInitialState is only invoked when the component is first created. The danger is that if the props on the component are changed without the component being ‘refreshed’, the new prop value will never be displayed because the constructor function (or getInitialState) will never update the current state of the component. The initialization of state from props only runs when the component is first created. #### Bad ```javascript class SampleComponent extends Component { // constructor function (or getInitialState) constructor(props) { super(props); this.state = { flag: false, inputVal: props.inputValue }; } render() { return
{this.state.inputVal && }
} } ``` #### Good ```javascript class SampleComponent extends Component { // constructor function (or getInitialState) constructor(props) { super(props); this.state = { flag: false }; } render() { return
{this.props.inputValue && }
} } ``` ### Related links: - [React Anti-Patterns: Props in Initial State](https://medium.com/@justintulk/react-anti-patterns-props-in-initial-state-28687846cc2e) - [Why is passing the component initial state a prop an anti-pattern?](http://stackoverflow.com/questions/28785106/reactjs-why-is-passing-the-component-initial-state-a-prop-an-anti-pattern) ================================================ FILE: anti-patterns/02.findDOMNode.md ================================================ # Refs over findDOMNode() Use callback refs over findDOMNode() Note: React also supports using a string (instead of a callback) as a ref prop on any component, although this approach is mostly legacy at this point. - [More about refs](https://reactjs.org/docs/refs-and-the-dom.html) - [Why ref-string is legacy?](http://stackoverflow.com/questions/37468913/why-ref-string-is-legacy) ##### findDOMNode(this) ###### Before: ```javascript class MyComponent extends Component { componentDidMount() { findDOMNode(this).scrollIntoView(); } render() { return
} } ``` ###### After ```javascript class MyComponent extends Component { componentDidMount() { this.node.scrollIntoView(); } render() { return
this.node = node}/> } } ``` ##### findDOMNode(stringDOMRef) ###### Before ```javascript class MyComponent extends Component { componentDidMount() { findDOMNode(this.refs.something).scrollIntoView(); } render() { return (
) } } ``` ###### After ```javascript class MyComponent extends Component { componentDidMount() { this.something.scrollIntoView(); } render() { return (
this.something = node}/>
) } } ``` ##### findDOMNode(childComponentStringRef) ###### Before: ```javascript class Field extends Component { render() { return } } class MyComponent extends Component { componentDidMount() { findDOMNode(this.refs.myInput).focus(); } render() { return (
Hello,
) } } ``` ###### After ```javascript class Field extends Component { render() { return ( ) } } class MyComponent extends Component { componentDidMount() { this.inputNode.focus(); } render() { return (
Hello, this.inputNode = node}/>
) } } ``` ### Related links: - [ESLint Rule proposal: warn against using findDOMNode()](https://github.com/yannickcr/eslint-plugin-react/issues/678#issue-165177220) - [Refs and the DOM](https://reactjs.org/docs/refs-and-the-dom.html) ================================================ FILE: anti-patterns/03.mixins.md ================================================ # Use Higher order components over Mixins #### Simple Example ```javascript // With Mixin var WithLink = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function () { return {message: 'Hello!'}; }, render: function () { return ; } }); // Move logic to a HOC var WithLink = React.createClass({ getInitialState: function () { return {message: 'Hello!'}; }, render: function () { return ; } }); ``` #### Detailed Example ```javascript // With Mixin var CarDataMixin = { componentDidMount: { // fetch car data and // call this.setState({carData: fetchedData}), // once data has been (asynchronously) fetched } }; var FirstView = React.createClass({ mixins: [CarDataMixin], render: function () { return (
) } }); // With HOC var bindToCarData = function (Component) { return React.createClass({ componentDidMount: { // fetch car data and // call this.setState({carData: fetchedData}), // once data has been (asynchronously) fetched }, render: function () { return } }); }; // Then wrap your component when you define it. var FirstView = bindToCarData(React.createClass({ render: function () { return (
) } })); ``` ### Related links: - [Mixins are dead - Long live higher ordercomponents](https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) - [Mixins are considered harmful](https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html) - [Stackoverflow: Using mixins vs components for code reuse](http://stackoverflow.com/questions/21854938/using-mixins-vs-components-for-code-reuse-in-facebook-react) - [Stackoverflow: Composition instead of mixins in React](http://stackoverflow.com/questions/30845561/how-to-solve-this-using-composition-instead-of-mixins-in-react) ================================================ FILE: anti-patterns/04.setState-in-componentWillMount.md ================================================ # setState() in componentWillMount() Avoid async initialization in ``componentWillMount()`` ``componentWillMount()`` is invoked immediately before mounting occurs. It is called before ``render()``, therefore setting state in this method will not trigger a re-render. Avoid introducing any side-effects or subscriptions in this method. Make async calls for component initialization in ``componentDidMount`` instead of ``componentWillMount`` ```javascript function componentDidMount() { axios.get(`api/messages`) .then((result) => { const messages = result.data console.log("COMPONENT WILL Mount messages : ", messages); this.setState({ messages: [...messages.content] }) }) } ``` ================================================ FILE: anti-patterns/05.mutating-state.md ================================================ # Mutating State without setState() - Causes state changes without making component re-render. - Whenever setState gets called in future, the mutated state gets applied. #### Bad ``` javascript class SampleComponent extends Component { constructor(props) { super(props); this.state = { items: ['foo', 'bar'] }; this.handleClick = this.handleClick.bind(this); } handleClick() { // BAD: We mutate state here this.state.items.push('lorem'); this.setState({ items: this.state.items }); } render() { return (
{this.state.items.length}
) } } ``` #### Good ``` javascript class SampleComponent extends Component { constructor(props) { super(props); this.state = { items: ['foo', 'bar'] }; this.handleClick = this.handleClick.bind(this); } handleClick() { // We update using setState() - concat return new array after appending new item. this.setState(prevState => ({ items: prevState.items.concat('lorem') })); } render() { return (
{this.state.items.length}
) } } ``` ### Related links: [React Design Patterns and best practices by Michele Bertoli.](https://github.com/MicheleBertoli/react-design-patterns-and-best-practices) ================================================ FILE: anti-patterns/06.using-indexes-as-key.md ================================================ # Using indexes as keys Keys should be stable, predictable, and unique so that React can keep track of elements. #### Bad In this snippet each element's key will be based on ordering, rather than tied to the data that is being represented. This limits the optimizations that React can do. ```javascript {todos.map((todo, index) => )} ``` #### Good Assuming `todo.id` is unique to this list and stable, React would be able to reorder elements without needing to reevaluate them as much. ```javascript {todos.map((todo) => )} ``` ### @Reference: - [React docs](https://reactjs.org/docs/reconciliation.html#tradeoffs) - [Lin Clark's code cartoon](https://youtu.be/-t8eOoRsJ7M?t=981) ================================================ FILE: anti-patterns/07.spreading-props-dom.md ================================================ # Spreading props on DOM elements When we spread props we run into the risk of adding unknown HTML attributes, which is a bad practice. #### Bad This will try to add the unknown HTML attribute `flag` to the DOM element. ```javascript const Sample = () => (); const Spread = (props) => (
Test
); ``` #### Good By creating props specifically for DOM attribute, we can safely spread. ```javascript const Sample = () => (); const Spread = (props) => (
Test
); ``` Or alternatively we can use prop destructuring with `...rest`: ```javascript const Sample = () => (); const Spread = ({ flag, ...domProps }) => (
Test
); ``` *Note* In [scenarios](https://github.com/vasanthk/react-bits/issues/34) where you use a [PureComponent](../perf-tips/02.pure-component.md), when an update happens it re-renders the component even if `domProps` did not change. This is because PureComponent only [shallowly compares](https://reactjs.org/docs/react-api.html#reactpurecomponent) the objects. ### Related links: - [React Design Patterns and best practices by Michele Bertoli.](https://github.com/MicheleBertoli/react-design-patterns-and-best-practices) - [In React, children are just props: Kent C. Dodds' Tweet](https://twitter.com/kentcdodds/status/851406788549369856) ================================================ FILE: anti-patterns/README.md ================================================ # Anti-patterns Familiarizing ourselves with common anti-patterns will help us understand how React works and describe useful forms of refactoring our code. ================================================ FILE: book.json ================================================ { "gitbook": ">3.0.0", "plugins": ["edit-link"], "pluginsConfig": { "edit-link": { "base": "https://github.com/vasanthk/react-bits/blob/master", "label": "Edit This Page" }, "github": { "url": "https://github.com/vasanthk/react-bits/" } } } ================================================ FILE: coding-style/README.md ================================================ # Coding Style **Disclaimer:** This section is purely to familiarize oneself with different coding styles out there. It is not a set of coding standards or conventions! ================================================ FILE: gotchas/01.pure-render-checks.md ================================================ # Pure Render Checks In order to preserve performance one needs to consider the creation of new entities in the render method. Pure render? With React.js pure render I mean components that implement the shouldComponentUpdate method with shallow equality checks. Examples of this are the React.PureComponent, PureRenderMixin, recompose/pure and many others. #### Case 1 ##### Bad ```javascript class Table extends PureComponent { render() { return (
{this.props.items.map(i => )}
); } } ``` **The issue is with ``{this.props.options || []}`` - it caused all the cells to be re-rendered even for a single cell change. Why?** You see the options array was passed deep down in the Cell elements. Normally this would not be an issue. The other Cell elements would not be re-rendered because they can do the cheap shallow equality check and skip the render entirely but in this case the options prop was null and the default array was used. As you should know the array literal is the same as new Array() which creates a new array instance. This completely destroyed every pure render optimization inside the Cell elements. In Javascript different instances have different identities and thus the shallow equality check always produces false and tells React to re-render the components. ##### Good ```javascript const defaultval = []; // <--- The fix (defaultProps could also have been used). class Table extends PureComponent { render() { return (
{this.props.items.map(i => )}
); } } ``` #### Case 2 Similar issue with using functions in render() as well ##### BAD ```javascript class App extends PureComponent { render() { return this.props.update(e.target.value)}/>; } } ``` ##### Bad again ```javascript class App extends PureComponent { update(e) { this.props.update(e.target.value); } render() { return ; } } ``` ^^In both cases a new function is created with a new identity. Just like with the array literal. We need to bind the function early ##### Good ```javascript class App extends PureComponent { constructor(props) { super(props); this.update = this.update.bind(this); } update(e) { this.props.update(e.target.value); } render() { return ; } } ``` ##### Bad ```javascript class Component extends React.Component { state = {clicked: false}; onClick() { this.setState({clicked: true}) } render() { // Options object created each render if not set const options = this.props.options || {test: 1}; return this.onClick(event) /> } } ``` ##### Good ```javascript class Component extends React.Component { state = {clicked: false}; options = {test: 1}; onClick = () => { this.setState({clicked: true}) }; render() { // Options object created once const options = this.props.options || this.options; return } } ``` ### Related links: - https://medium.com/@esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f - https://github.com/nfour/js-structures/blob/master/guides/react-anti-patterns.md#pure-render-immutability - [Optimizing React Rendering](https://flexport.engineering/optimizing-react-rendering-part-1-9634469dca02) ================================================ FILE: gotchas/02.synthetic-events.md ================================================ # Synthetic events in React Inside React event handlers, the event object is wrapped in a SyntheticEvent object. These objects are pooled, which means that the objects received at an event handler will be reused for other events to increase performance. This also means that accessing the event object’s properties asynchronously will be impossible since the event’s properties have been reset due to reuse. The following piece of code will log null because event has been reused inside the SyntheticEvent pool: ```javascript function handleClick(event) { setTimeout(function () { console.log(event.target.name); }, 1000); } ``` To avoid this you need to store the event’s property you are interested in inside its own binding: ```javascript function handleClick(event) { let name = event.target.name; setTimeout(function () { console.log(name); }, 1000); } ``` ### Related links: - [React/Redux: Best practices & gotchas](https://medium.com/nick-parsons/react-redux-best-practices-gotchas-56cf61c1c415) - [React events in depth w/ Kent C. Dodds, Ben Alpert, & Dan Abramov](https://www.youtube.com/watch?v=dRo_egw7tBc) ================================================ FILE: gotchas/README.md ================================================ # Gotchas React is intuitive for the most part, but there are quite a few stumbling points which might catch you by surprise. We'll discuss more on them here. ## Articles [React Gotchas](https://daveceddia.com/react-gotchas/) [Top 5 React Gotchas](http://joelgriffith.net/top-5-react-gotchas/) ================================================ FILE: package.json ================================================ { "name": "react-bits", "version": "1.0.0", "repository": "https://github.com/vasanthk/react-bits.git", "author": "", "license": "MIT", "scripts": { "docs": "gitbook serve" } } ================================================ FILE: patterns/1.conditionals-in-jsx.md ================================================ # Conditionals in JSX Instead of ```javascript const sampleComponent = () => { return isTrue ?

True!

: null }; ``` Use short-circuit evaluation ```javascript const sampleComponent = () => { return isTrue &&

True!

}; ``` For Complex scenarios with too many ternaries: ```javascript // Y soo many ternary??? :-/ const sampleComponent = () => { return (
{flag && flag2 && !flag3 ? flag4 ?

Blah

: flag5 ?

Meh

:

Herp

:

Derp

}
) }; ``` - Best approach: Move logic to sub-components - Alternate hacky approach: Use IIFE There are some libraries that solve this problem (JSX-Control Statements), but rather than introduce another dependency use an [IIFE](http://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript) and return values by using if-else statement inside ```javascript const sampleComponent = () => { return (
{ (() => { if (flag && flag2 && !flag3) { if (flag4) { return

Blah

} else if (flag5) { return

Meh

} else { return

Herp

} } else { return

Derp

} })() }
) }; ``` With an appropiate [transpiler](https://babeljs.io/docs/plugins/transform-do-expressions/) you can take advantage of the upcoming [do expression](https://github.com/tc39/proposal-do-expressions) which is currently on [stage-1](https://github.com/tc39/proposal-do-expressions) ```javascript const sampleComponent = () => { return (
{ do { if (flag && flag2 && !flag3) { if (flag4) { return

Blah

; } else if (flag5) { return

Meh

; } else { return

Herp

; } } else { return

Derp

; } } }
) }; ``` Or alternatively simply use early returns ```javascript const sampleComponent = () => { const basicCondition = flag && flag2 && !flag3; if (!basicCondition) return

Derp

; if (flag4) return

Blah

; if (flag5) return

Meh

; return

Herp

} ``` ### Related links: - https://engineering.musefind.com/our-best-practices-for-writing-react-components-dec3eb5c3fc8 - [Conditional rendering](https://reactjs.org/docs/conditional-rendering.html) ================================================ FILE: patterns/10.passing-function-to-setState.md ================================================ # Passing a function to setState Here’s the dirty secret about setState — it’s actually asynchronous. React batches state changes for performance reasons, so the state may not change immediately after setState is called. That means you should not rely on the current state when calling setState — since you can’t be sure what that state will be! Here’s the solution — pass a function to setState, with the previous state as an argument. Doing so avoids issues with the user getting the old state value on access (due to the asynchrony of setState) #### Problem ```javascript // assuming this.state.count === 0 this.setState({count: this.state.count + 1}); this.setState({count: this.state.count + 1}); this.setState({count: this.state.count + 1}); // this.state.count === 1, not 3 ``` #### Solution ```javascript this.setState((prevState, props) => ({ count: prevState.count + props.increment })); ``` #### Variations ```javascript // Passing object this.setState({ expanded: !this.state.expanded }); // Passing function this.setState(prevState => ({ expanded: !prevState.expanded })); ``` ### Related links: - [setState() Gate](https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82) - [Do I need to use setState(function) overload in this case?](http://stackoverflow.com/questions/43428456/do-i-need-to-use-setstatefunction-overload-in-this-case/43440790#43440790) - [Functional setState is the future of React](https://medium.freecodecamp.com/functional-setstate-is-the-future-of-react-374f30401b6b) ================================================ FILE: patterns/11.decorators.md ================================================ # Decorators Decorators (*supported by Babel, in Stage 2 proposal as of 03/17*) If you’re using something like mobx, you can decorate your class components — which is the same as passing the component into a function. Decorators are flexible and readable way of modifying component functionality. Non-decorators approach ```javascript class ProfileContainer extends Component { // Component code } export default observer(ProfileContainer) ``` With decorators ```javascript @observer export default class ProfileContainer extends Component { // Component code } ``` ### Article: - [Enhancing React components with Decorators](https://medium.com/@gigobyte/enhancing-react-components-with-decorators-441320e8606a) ### Related: - [Decorators != higher ordered components](https://twitter.com/dan_abramov/status/628202050946514944) - [React Decorator example - Module](https://github.com/gigobyte/react-document-title-decorator) - [What is the use of Connect(decorator in react-redux)](http://stackoverflow.com/questions/36553814/what-is-the-use-of-connect-decorator-in-react-redux) - [Decorators with React Components](http://stackoverflow.com/questions/36286384/decorators-with-react-components) - [Exploring ES7 decorators](https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841#.8cbzw5wcl) - [Understanding Decorators](https://survivejs.com/react/appendices/understanding-decorators/) ================================================ FILE: patterns/12.feature-flags-using-redux.md ================================================ # Feature Flags Enabling Feature flags in React using Redux ```javascript // createFeatureFlaggedContainer.js import React from 'react'; import { connect } from 'react-redux'; import { isFeatureEnabled } from './reducers' export default function createFeatureFlaggedContainer({ featureName, enabledComponent, disabledComponent }) { function FeatureFlaggedContainer({ isEnabled, ...props }) { const Component = isEnabled ? enabledComponent : disabledComponent; if (Component) { return ; } // `disabledComponent` is optional property return null; } // Having `displayName` is very useful for debugging. FeatureFlaggedContainer.displayName = `FeatureFlaggedContainer(${ featureName })`; return connect((store) => { isEnabled: isFeatureEnabled(store, featureName) })(FeatureFlaggedContainer); } ``` ```javascript // EnabledFeature.js import { connect } from 'react-redux'; import { isFeatureEnabled } from './reducers' function EnabledFeature({ isEnabled, children }) { if (isEnabled) { return children; } return null; } export default connect((store, { name }) => { isEnabled: isFeatureEnabled(store, name) })(EnabledFeature); ``` ```javascript // featureEnabled.js import createFeatureFlaggedContainer from './createFeatureFlaggedContainer' // Decorator for "Page" components. // usage: enabledFeature('unicorns')(UnicornsPage); export default function enabledFeature(featureName) { return (Component) => { return createFeatureFlaggedContainer({ featureName, enabledComponent: Component, disabledComponent: PageNotFound, // 404 page or something similar }); }; }; ``` ```javascript // features.js // This is quite simple reducer, containing only an array of features. // You can attach this data to a `currentUser` or similar reducer. // `BOOTSTAP` is global action, which contains the initial data for a page // Features access usually don't change during user usage of a page const BOOTSTAP = 'features/receive'; export default function featuresReducer(state, { type, payload }) { if (type === BOOTSTAP) { return payload.features || []; } return state || []; } export function isFeatureEnabled(features, featureName) { return features.indexOf(featureName) !== -1; } ``` ```javascript // reducers.js // This is your main reducer.js file import { combineReducers } from 'redux'; import features, { isFeatureEnabled as isFeatureEnabledSelector } from './features'; // ...other reducers export default combineReducers({ features // ...other reducers }); // This is the important part, access to `features` reducer should only happens // via this selector. // Then you can always change where/how the features are stored. export function isFeatureEnabled({ features }, featureName) { return isFeatureEnabledSelector(features, featureName); } ``` ### Related links: - [Feature flags in React](http://blog.rstankov.com/feature-flags-in-react/) - [Gist](https://gist.github.com/RStankov/0e764f27daf38f2fcd81b82360334528) ================================================ FILE: patterns/13.component-switch.md ================================================ # The switching component A switching component is a component that renders one of many components. Use an object to map prop values to components ```javascript import HomePage from './HomePage.jsx'; import AboutPage from './AboutPage.jsx'; import UserPage from './UserPage.jsx'; import FourOhFourPage from './FourOhFourPage.jsx'; const PAGES = { home: HomePage, about: AboutPage, user: UserPage }; const Page = (props) => { const Handler = PAGES[props.page] || FourOhFourPage; return }; // The keys of the PAGES object can be used in the prop types to catch dev-time errors. Page.propTypes = { page: PropTypes.oneOf(Object.keys(PAGES)).isRequired }; ``` ### Related links: - https://hackernoon.com/10-react-mini-patterns-c1da92f068c5 ================================================ FILE: patterns/14.reaching-into-a-component.md ================================================ # Reaching into a Component Accessing a component from the parent. eg. Autofocus an input (controlled by parent component) #### Child Component An input component with a focus() method that focuses the HTML element ```javascript class Input extends Component { focus() { this.el.focus(); } render() { return ( { this.el = el; }} /> ); } } ``` #### Parent Component In the parent component, we can get a reference to the Input component and call its focus() method. ```javascript class SignInModal extends Component { componentDidMount() { // Note that when you use ref on a component, it’s a reference to // the component (not the underlying element), so you have access to its methods. this.InputComponent.focus(); } render() { return (
{ this.InputComponent = comp; }} />
) } } ``` ### Reference: - https://hackernoon.com/10-react-mini-patterns-c1da92f068c5 ================================================ FILE: patterns/15.list-components.md ================================================ # Lists Components Lists and other things that are almost components Instead of making a separate component for lists I can then generate the results like: ```javascript // renderSearchSuggestion() behaves as a pseudo SearchSuggestion component // keep it self contained and it should be easy to extract later if needed const renderSearchSuggestion = listItem => (
  • {listItem.name} {listItem.id}
  • ); const SearchSuggestions = (props) => { return (
      {props.listItems.map(renderSearchSuggestion)}
    ); }; ``` If things get more complex or you want to use this component elsewhere, you should be able to copy/paste the code out into a new component. Don’t prematurely componentize. ### Related links: - https://hackernoon.com/10-react-mini-patterns-c1da92f068c5 ================================================ FILE: patterns/16.format-text-via-component.md ================================================ # Components for formatting text Instead of formatting text by calling helper functions inside render, we can create a separate component that handles this. #### With Component Render function is lot cleaner to comprehend as it is just simple component composition. ```javascript const Price = (props) => { // toLocaleString is not React specific syntax - it is a native JavaScript function used fo formatting // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString const price = props.children.toLocaleString('en', { style: props.showSymbol ? 'currency' : undefined, currency: props.showSymbol ? 'USD' : undefined, maximumFractionDigits: props.showDecimals ? 2 : 0 }); return {price} }; Price.propTypes = { className: PropTypes.string, children: PropTypes.number, showDecimals: PropTypes.bool, showSymbol: PropTypes.bool }; Price.defaultProps = { children: 0, showDecimals: true, showSymbol: true, }; const Page = () => { const lambPrice = 1234.567; const jetPrice = 999999.99; const bootPrice = 34.567; return (

    One lamb is {lambPrice}

    One jet is {jetPrice}

    Those gumboots will set ya back {bootPrice} bucks.

    ); }; ``` #### Without Component Less code: But render looks less clean. (Debatable, yeah I understand) ```javascript function numberToPrice(num, options = {}) { const showSymbol = options.showSymbol !== false; const showDecimals = options.showDecimals !== false; return num.toLocaleString('en', { style: showSymbol ? 'currency' : undefined, currency: showSymbol ? 'USD' : undefined, maximumFractionDigits: showDecimals ? 2 : 0 }); } const Page = () => { const lambPrice = 1234.567; const jetPrice = 999999.99; const bootPrice = 34.567; return (

    One lamb is {numberToPrice(lambPrice)}

    One jet is {numberToPrice(jetPrice, { showDecimals: false })}

    Those gumboots will set ya back {numberToPrice(bootPrice, { showDecimals: false, showSymbol: false })} bucks.

    ); }; ``` ### Reference: - [10 React Mini Patterns](https://hackernoon.com/10-react-mini-patterns-c1da92f068c5) ================================================ FILE: patterns/17.react-fragments.md ================================================ # React Fragments React fragments are used whenever a component needs returned with multiple children. Specifically, fragments are useful when I don't want to clutter the DOM with unnecessary `
    ` tags that are used purely to wrap children in a React render method. For example, React fragments are commonly used to render list items: ```javascript render() { return ( Table Cell 1 Table Cell 2 ); } ``` This solves the issue of breaking the DOM HTML table specifications by not adding unnecessary `
    ` elements around `` elements. Do keep in mind, if it is a list being rendered, React does still throw warnings when children don't have the `key={}` prop. ### Related links: - https://reactjs.org/docs/fragments.html ================================================ FILE: patterns/18.share-tracking-logic.md ================================================ # Share Tracking Logic Using HOC to share tracking logic across various UX components eg. Adding analytics tracking across various components. - Helps to keep it DRY (Do not Repeat Yourself) - Removing tracking logic etc. from the presentational component makes it well testable, which is key. ```javascript import tracker from './tracker.js'; // HOC const pageLoadTracking = (ComposedComponent) => class HOC extends Component { componentDidMount() { tracker.trackPageLoad(this.props.trackingData); } componentDidUpdate() { tracker.trackPageLoad(this.props.trackingData); } render() { return } }; // Usage import LoginComponent from "./login"; const LoginWithTracking = pageLoadTracking(LoginComponent); class SampleComponent extends Component { render() { const trackingData = {/** Nested Object **/}; return } } ``` ================================================ FILE: patterns/2.async-nature-of-setState.md ================================================ # Async Nature Of setState() On the Async nature of setState() ## Gist: React batches updates and flushes it out once per frame (perf optimization) However, in some cases React has no control over batching, hence updates are made synchronously e.g. eventListeners, Ajax, setTimeout and similar Web APIs. ### Main Idea setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains. #### Run the below code and you will make the following observations: You can see that in every situation (addEventListener, setTimeout or AJAX call) the state before and the state after are different. And that render was called immediately after triggering the setState method. But why is that? Well, it turns out React does not understand and thus cannot control code that doesn't live inside the library. Timeouts or AJAX calls for example, are developer authored code that executes outside of the context of React. So why does React synchronously update the state in these cases? Well, because it's trying to be as defensive as possible. Not being in control means it's not able to do any performance optimisations so it's better to update the state on spot and make sure the code that follows has access to the latest information available. ```javascript class TestComponent extends React.Component { constructor(...args) { super(...args); this.state = { dollars: 10 }; this._saveButtonRef = (btn => { this._btnRef = btn }); [ '_onTimeoutHandler', '_onMouseLeaveHandler', '_onClickHandler', '_onAjaxCallback', ].forEach(propToBind => { this[propToBind] = this[propToBind].bind(this); }); } componentDidMount() { // Add custom event via `addEventListener` // // The list of supported React events does include `mouseleave` // via `onMouseLeave` prop // // However, we are not adding the event the `React way` - this will have // effects on how state mutates // // Check the list here - https://reactjs.org/docs/events.html this._btnRef.addEventListener('mouseleave', this._onMouseLeaveHandler); // Add JS timeout // // Again,outside React `world` - this will also have effects on how state // mutates setTimeout(this._onTimeoutHandler, 10000); // Make AJAX request fetch('https://api.github.com/users') .then(this._onAjaxCallback); } render() { console.log('State in render: ' + JSON.stringify(this.state)); return ( ); } _onClickHandler() { console.log('State before (_onClickHandler): ' + JSON.stringify(this.state)); this.setState({ dollars: this.state.dollars + 10 }); console.log('State after (_onClickHandler): ' + JSON.stringify(this.state)); } _onMouseLeaveHandler() { console.log('State before (mouseleave): ' + JSON.stringify(this.state)); this.setState({ dollars: this.state.dollars + 20 }); console.log('State after (mouseleave): ' + JSON.stringify(this.state)); } _onTimeoutHandler() { console.log('State before (timeout): ' + JSON.stringify(this.state)); this.setState({ dollars: this.state.dollars + 30 }); console.log('State after (timeout): ' + JSON.stringify(this.state)); } _onAjaxCallback(response) { if (response.status !== 200) { console.log('Error in AJAX call: ' + response.statusText); return; } console.log('State before (AJAX call): ' + JSON.stringify(this.state)); this.setState({ dollars: this.state.dollars + 40 }); console.log('State after (AJAX call): ' + JSON.stringify(this.state)); } }; // Render to DOM ReactDOM.render( , document.getElementById('app') ); ``` ### Possible solution? We're used to calling setState with one parameter only, but actually, the method's signature support two. The second argument that you can pass in is a callback function that will always be executed after the state has been updated (whether it's inside React's known context or outside of it). #### An example might be: ```javascript _onClickHandler: function _onClickHandler() { console.log('State before (_onClickHandler): ' + JSON.stringify(this.state)); this.setState({ dollars: this.state.dollars + 10 }, () => { console.log('Here state will always be updated to latest version!'); console.log('State after (_onClickHandler): ' + JSON.stringify(this.state)); }); } ``` #### A note on the async nature of setstate To be politically correct, setState, as a method, is always synchronous. It's just a function that calls something behind the scenes - enqueueState or enqueueCallback on updater. In fact, here's setState taken directly from React source code: ```javascript ReactComponent.prototype.setState = function(partialState, callback) { invariant( typeof partialState === 'object' || typeof partialState === 'function' || partialState == null, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.' ); this.updater.enqueueSetState(this, partialState); if (callback) { this.updater.enqueueCallback(this, callback, 'setState'); } }; ``` What's actually sync or async are the effects of calling setState in a React application - the reconciliation algorithm, doing the VDOM comparisons and calling render to update the real DOM. ## Related links: - https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3#.jhdhncws3 - https://www.bennadel.com/blog/2893-setstate-state-mutation-operation-may-be-synchronous-in-reactjs.htm ================================================ FILE: patterns/3.dependency-injection.md ================================================ # Dependency Injection In React the need of [dependency injection](https://www.youtube.com/watch?v=IKD2-MAkXyQ) is easily visible. Let's consider the following application tree: ```javascript // Title.jsx export default function Title(props) { return

    { props.title }

    ; } ``` ```javascript // Header.jsx import Title from './Title.jsx'; export default function Header() { return (
    </header> ); } ``` ```javascript // App.jsx import Header from './Header.jsx'; class App extends React.Component { constructor(props) { super(props); this.state = { title: 'React Dependency Injection' }; } render() { return <Header />; } } ``` The string "React Dependency Injection" should somehow reach the Title component. The direct way of doing this is to pass it from App to Header and then Header to pass it to Title. However, this may work for these three components but what happens if there are multiple properties and deeper nesting. Lots of components will have to mention properties that they are not interested in. It is clear that most React components receive their dependencies via props but the question is how these dependencies reach that point. One way to achieve dependency injection is by using higher-order component to inject data. ```javascript // inject.jsx var title = 'React Dependency Injection'; export default function inject(Component) { return class Injector extends React.Component { render() { return ( <Component {...this.state} {...this.props} title={ title } /> ) } }; } ``` ```javascript // Title.jsx export default function Title(props) { return <h1>{ props.title }</h1>; } ``` ```javascript // Header.jsx import inject from './inject.jsx'; import Title from './Title.jsx'; var EnhancedTitle = inject(Title); export default function Header() { return ( <header> <EnhancedTitle /> </header> ); } ``` The title is hidden in a middle layer (higher-order component) where we pass it as a prop to the original Title component. That's all nice but it solves only half of the problem. Now we don't have to pass the title down the tree but how this data will reach the enhance.jsx helper. ## Using React's context React has the concept of context. The context is something that every component may have access to. It's something like an event bus but for data. A single model which we can access from everywhere. a place where we'll define the context ```javascript var context = { title: 'React in patterns' }; class App extends React.Component { getChildContext() { return context; } // ... } App.childContextTypes = { title: PropTypes.string }; ``` A place where we need data ```javascript class Inject extends React.Component { render() { var title = this.context.title; // ... } } Inject.contextTypes = { title: PropTypes.string }; ``` ### Related links: - [What is Dependency Injection?](https://www.youtube.com/watch?v=IKD2-MAkXyQ) - [The Basics of Dependency Injection](https://www.youtube.com/watch?v=jXhdOTw1q5Q) - [Dependency injection in JavaScript](http://krasimirtsonev.com/blog/article/Dependency-injection-in-JavaScript) - [DI In React](https://github.com/krasimir/react-in-patterns/blob/master/book/chapter-10/README.md) ================================================ FILE: patterns/4.context-wrapper.md ================================================ # Context Wrapper It is a good practice that our context is not just a plain object but it has an interface that allows us to store and retrieve data. For example: ```javascript // dependencies.js export default { data: {}, get(key) { return this.data[key]; }, register(key, value) { this.data[key] = value; } } ``` Then, if we go back to our example, the very top App component may look like that: ```javascript import dependencies from './dependencies'; dependencies.register('title', 'React in patterns'); class App extends React.Component { getChildContext() { return dependencies; } render() { return <Header />; } } App.childContextTypes = { data: PropTypes.object, get: PropTypes.func, register: PropTypes.func }; ``` And our Title component gets it's data through the context: ```javascript // Title.jsx export default class Title extends React.Component { render() { return <h1>{ this.context.get('title') }</h1> } } Title.contextTypes = { data: PropTypes.object, get: PropTypes.func, register: PropTypes.func }; ``` Ideally we don't want to specify the contextTypes every time when we need an access to the context. This detail may be wrapped in a higher-order component. And even more, we may write an utility function that is more descriptive and helps us declare the exact wiring. ie. instead of accessing the context directly with this.context.get('title') we ask the higher-order component to get what we need and to pass it as a prop to our component. For example: ```javascript // Title.jsx import wire from './wire'; function Title(props) { return <h1>{ props.title }</h1>; } export default wire(Title, ['title'], function resolve(title) { return { title }; }); ``` The wire function accepts first a React component, then an array with all the needed dependencies (which are registered already) and then a function which I like to call mapper. It receives what's stored in the context as a raw data and returns an object which is the actual React props for our component (Title). In this example we just pass what we get - a title string variable. However, in a real app this could be a collection of data stores, configuration or something else. So, it's nice that we pass exactly what we need and don't pollute the components with data that they don't need. Here is how the wire function looks like: ```javascript export default function wire(Component, dependencies, mapper) { class Inject extends React.Component { render() { var resolved = dependencies.map(this.context.get.bind(this.context)); var props = mapper(...resolved); return React.createElement(Component, props); } } Inject.contextTypes = { data: PropTypes.object, get: PropTypes.func, register: PropTypes.func }; return Inject; }; ``` Inject is a higher-order component that gets access to the context and retrieves all the items listed under dependencies array. The mapper is a function receiving the context data and transforms it to props for our component. #### Non-context alternative Use a singleton to register/fetch all dependencies ```javascript var dependencies = {}; export function register(key, dependency) { dependencies[key] = dependency; } export function fetch(key) { if (key in dependencies) return dependencies[key]; throw new Error(`"${ key } is not registered as dependency.`); } export function wire(Component, deps, mapper) { return class Injector extends React.Component { constructor(props) { super(props); this._resolvedDependencies = mapper(...deps.map(fetch)); } render() { return ( <Component {...this.state} {...this.props} {...this._resolvedDependencies} /> ); } }; } ``` We'll store the dependencies in dependencies global variable (it's global for our module, not at an application level). We then export two functions register and fetch that write and read entries. It looks a little bit like implementing setter and getter against a simple JavaScript object. Then we have the wire function that accepts our React component and returns a higher-order component. In the constructor of that component we are resolving the dependencies and later while rendering the original component we pass them as props. We follow the same pattern where we describe what we need (deps argument) and extract the needed props with a mapper function. Having the di.jsx helper we are again able to register our dependencies at the entry point of our application (app.jsx) and inject them wherever (Title.jsx) we need. ```javascript // app.jsx import Header from './Header.jsx'; import { register } from './di.jsx'; register('my-awesome-title', 'React in patterns'); class App extends React.Component { render() { return <Header />; } } ``` ```javascript // Header.jsx import Title from './Title.jsx'; export default function Header() { return ( <header> <Title /> </header> ); } ``` ```javascript // Title.jsx import { wire } from './di.jsx'; var Title = function(props) { return <h1>{ props.title }</h1>; }; export default wire(Title, ['my-awesome-title'], title => ({ title })); ``` If we look at the `Title.jsx` file we'll see that the actual component and the wiring may live in different files. That way the component and the mapper function become easily unit testable. ================================================ FILE: patterns/5.event-handlers.md ================================================ # Event Handlers Binding event handlers in the constructor. Most of the times we handle DOM events in the component that contains the elements dispatching the events. Like in the example below, we have a click handler and we want to run a function or method of the same component: ```javascript class Switcher extends React.Component { render() { return ( <button onClick={ this._handleButtonClick }> click me </button> ); } _handleButtonClick() { console.log('Button is clicked'); } } ``` That's all fine because `_handleButtonClick` is a function and we indeed pass a function to the onClick attribute. The problem is that as it is the code doesn't keep the scope. So, if we have to use `this` inside `_handleButtonClick` we'll get an error. ```javascript class Switcher extends React.Component { constructor(props) { super(props); this.state = { name: 'React in patterns' }; } render() { return ( <button onClick={ this._handleButtonClick }> click me </button> ); } _handleButtonClick() { console.log(`Button is clicked inside ${ this.state.name }`); // leads to // Uncaught TypeError: Cannot read property 'state' of null } } ``` What we normally do is to use bind like so: ```javascript <button onClick={ this._handleButtonClick.bind(this) }> click me </button> ``` However, this means that the bind function is called again and again because we may render the button many times. A better approach would be to create the bindings in the constructor of the component: ```javascript class Switcher extends React.Component { constructor(props) { super(props); this.state = { name: 'React in patterns' }; this._buttonClick = this._handleButtonClick.bind(this); } render() { return ( <button onClick={ this._buttonClick }> click me </button> ); } _handleButtonClick() { console.log(`Button is clicked inside ${ this.state.name }`); } } ``` The other alternative is to use arrow functions for the onClick prop function assignment. Arrow functions don't affect the context at invocation time (`this` value from the surrounding scope is used). Facebook by the way recommend the same technique while dealing with functions that need the context of the same component. The binding in the constructor may be also useful if we pass callbacks down the tree. A short hand example using arrow functions and avoid having to use the constructor: ```javascript class Switcher extends React.Component { state = { name: 'React in patterns' }; render() { return ( <button onClick={ this._handleButtonClick }> click me </button> ); } _handleButtonClick = () => { console.log(`Button is clicked inside ${ this.state.name }`); } } ``` ================================================ FILE: patterns/6.flux-pattern.md ================================================ # Flux pattern for data handling **Simple dispatcher** ```javascript var Dispatcher = function () { return { _stores: [], register: function (store) { this._stores.push({store: store}); }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action); }); } } } }; ``` We expect the store to have an update method(), so let's modify register to expect it. ```javascript function register(store) { if (!store || !store.update || typeof store.update !== 'function') { throw new Error('You should provide a store that has an update method'); } else { this._stores.push({store: store}); } } ``` **Full blown Dispatcher** ```javascript var Dispatcher = function () { return { _stores: [], register: function (store) { if (!store || !store.update) { throw new Error('You should provide a store that has an `update` method.'); } else { var consumers = []; var change = function () { consumers.forEach(function (l) { l(store); }); }; var subscribe = function (consumer, noInit) { consumers.push(consumer); !noInit ? consumer(store) : null; }; this._stores.push({store: store, change: change}); return subscribe; } }, dispatch: function (action) { if (this._stores.length > 0) { this._stores.forEach(function (entry) { entry.store.update(action, entry.change); }); } } } }; module.exports = { create: function () { var dispatcher = Dispatcher(); return { createAction: function (type) { if (!type) { throw new Error('Please, provide action\'s type.'); } else { return function (payload) { return dispatcher.dispatch({type: type, payload: payload}); } } }, createSubscriber: function (store) { return dispatcher.register(store); } } } }; ``` ### Related links: - https://github.com/krasimir/react-in-patterns/tree/master/patterns/flux ================================================ FILE: patterns/7.one-way-data-flow.md ================================================ # One way data flow One-way direction data flow eliminates multiple states and deals with only one which is usually inside the store. To achieve that our Store object needs logic that allows us to subscribe for changes: ```javascript var Store = { _handlers: [], _flag: '', onChange: function (handler) { this._handlers.push(handler); }, set: function (value) { this._flag = value; this._handlers.forEach(handler => handler()) }, get: function () { return this._flag; } }; ``` Then we will hook our main App component and we'll re-render it every time when the Store changes its value: ```javascript class App extends React.Component { constructor(props) { super(props); Store.onChange(this.forceUpdate.bind(this)); } render() { return ( <div> <Switcher value={ Store.get() } onChange={ Store.set.bind(Store) }/> </div> ); } } ``` Notice that we are using forceUpdate which is not really recommended. Normally a high-order component is used to enable the re-rendering. We used forceUpdate just to keep the example simple. Because of this change the Switcher becomes really simple. We don't need the internal state: ```javascript class Switcher extends React.Component { constructor(props) { super(props); this._onButtonClick = e => { this.props.onChange(!this.props.value); } } render() { return ( <button onClick={ this._onButtonClick }> { this.props.value ? 'lights on' : 'lights off' } </button> ); } } ``` The benefit that comes with this pattern is that our components become dummy representation of the Store's data. It's really easy to think about the React components as views (renderers). We write our application in a declarative way and deal with the complexity in only one place. ### Related links: - https://www.startuprocket.com/articles/evolution-toward-one-way-data-flow-a-quick-introduction-to-redux ================================================ FILE: patterns/8.presentational-vs-container.md ================================================ # Presentational and Container components #### Problem Data and logic together. ```javascript class Clock extends React.Component { constructor(props) { super(props); this.state = {time: this.props.time}; this._update = this._updateTime.bind(this); } render() { var time = this._formatTime(this.state.time); return ( <h1>{ time.hours } : { time.minutes } : { time.seconds }</h1> ); } componentDidMount() { this._interval = setInterval(this._update, 1000); } componentWillUnmount() { clearInterval(this._interval); } _formatTime(time) { var [ hours, minutes, seconds ] = [ time.getHours(), time.getMinutes(), time.getSeconds() ].map(num => num < 10 ? '0' + num : num); return {hours, minutes, seconds}; } _updateTime() { this.setState({time: new Date(this.state.time.getTime() + 1000)}); } } ReactDOM.render(<Clock time={ new Date() }/>, ...); ``` #### Solution Let's split the component into two parts - container and presentation. #### Container Component Containers know about data, it's shape and where it comes from. They know details about how the things work or the so called business logic. They receive information and format it so it is easy to use by the presentational component. Very often we use higher-order components to create containers. Their render method contains only the presentational component. ```javascript // Clock/index.js import Clock from './Clock.jsx'; // <-- that's the presentational component export default class ClockContainer extends React.Component { constructor(props) { super(props); this.state = {time: props.time}; this._update = this._updateTime.bind(this); } render() { return <Clock { ...this._extract(this.state.time) }/>; } componentDidMount() { this._interval = setInterval(this._update, 1000); } componentWillUnmount() { clearInterval(this._interval); } _extract(time) { return { hours: time.getHours(), minutes: time.getMinutes(), seconds: time.getSeconds() }; } _updateTime() { this.setState({time: new Date(this.state.time.getTime() + 1000)}); } }; ``` #### Presentational component Presentational components are concerned with how the things look. They have the additional markup needed for making the page pretty. Such components are not bound to anything and have no dependencies. Very often implemented as a stateless functional components they don't have internal state. ```javascript // Clock/Clock.jsx export default function Clock(props) { var [ hours, minutes, seconds ] = [ props.hours, props.minutes, props.seconds ].map(num => num < 10 ? '0' + num : num); return <h1>{ hours } : { minutes } : { seconds }</h1>; }; ``` The nice things about containers is that they encapsulate logic and may inject data into different renderers. Very often a file that exports a container is not sending out a class directly but a function. For example, instead of using ```javascript import Clock from './Clock.jsx'; export default class ClockContainer extends React.Component { render() { return <Clock />; } } ``` We may export a function that accepts the presentational component: ```javascript export default function (Component) { return class Container extends React.Component { render() { return <Component />; } } } ``` Using this technique our container is really flexible in rendering its result. It will be really helpful if we want to switch from digital to analog clock representation. ### Related links: - https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.mbglcakmp - https://github.com/krasimir/react-in-patterns/tree/master/patterns/presentational-and-container - https://medium.com/@learnreact/container-components-c0e67432e005 ================================================ FILE: patterns/9.third-party-integration.md ================================================ # Third Party Integration Mixing 3rd party integrations/libraries with React In this example we'll see how to mix React and jQuery's UI plugin. We pick tag-it jQuery plugin for the example. It transforms an unordered list to input field for managing tags: ```html <ul> <li>JavaScript</li> <li>CSS</li> </ul> ``` To make it work we have to include jQuery, jQuery UI and the tag-it plugin code. It works like that: ```javascript $('<dom element selector>').tagit(); ``` We select a DOM element and call tagit(). The very first thing that we have to do is to force a single-render of the Tags component. That's because when React adds the elements in the actual DOM we want to pass the control of them to jQuery. If we skip this both React and jQuery will work on same DOM elements without knowing for each other. To achieve a single-render we have to use the lifecycle method `shouldComponentUpdate` Let's say that we want to programmatically add a new tag to the already running tag-it field. Such action will be triggered by the React component and needs to use the jQuery API. We have to find a way to communicate data to Tags component but still keep the single-render approach. To illustrate the whole process we will add an input field to the App class and a button which if clicked will pass a string to Tags component. ```javascript class App extends React.Component { constructor(props) { super(props); this._addNewTag = this._addNewTag.bind(this); this.state = { tags: ['JavaScript', 'CSS'], newTag: null }; } _addNewTag() { this.setState({newTag: this.refs.field.value}); } render() { return ( <div> <p>Add new tag:</p> <div> <input type='text' ref='field'/> <button onClick={ this._addNewTag }>Add</button> </div> <Tags tags={ this.state.tags } newTag={ this.state.newTag }/> </div> ); } } ``` We use the internal state as a data storage for the value of the newly added field. Every time when we click the button we update the state and trigger re-rendering of Tags component. However, because of shouldComponentUpdate we update nothing. The only one change is that we get a value of the newTag prop which may be captured via another lifecycle method - componentWillReceiveProps ```javascript class Tags extends React.Component { componentDidMount() { this.list = $(this.refs.list); this.list.tagit(); } shouldComponentUpdate() { return false; } componentWillReceiveProps(newProps) { this.list.tagit('createTag', newProps.newTag); } render() { return ( <ul ref='list'> { this.props.tags.map((tag, i) => <li key={ i }>{ tag } </li>) } </ul> ); } } ``` ### Related links: - https://github.com/krasimir/react-in-patterns/tree/master/patterns/third-party ================================================ FILE: perf-tips/01.shouldComponentUpdate-check.md ================================================ # shouldComponentUpdate() check `shouldComponentUpdate` check to avoid expensive re-renders React Components re-render every time their props or state change. So imagine having to render the entire page every time there in an action. That takes a big load on the browser. That’s where ShouldComponentUpdate comes in, whenever React is rendering the view it checks to see if shouldComponentUpdate is returning false/true. So whenever you have a component that’s static do yourself a favor and return false. Or if is not static check to see if the props/state has changed. #### Bad ```javascript const AutocompleteItem = (props) => { const selectedClass = props.selected === true ? "selected" : ""; var path = parseUri(props.url).path; path = path.length <= 0 ? props.url : "..." + path; return ( <li onMouseLeave={props.onMouseLeave} className={selectedClass}> <i className="ion-ios-eye" data-image={props.image} data-url={props.url} data-title={props.title} onClick={props.handlePlanetViewClick}/> <span onMouseEnter={props.onMouseEnter} > <div className="dot bg-mint"/> {path} </span> </li> ); }; ``` #### Good ```javascript export default class AutocompleteItem extends React.Component { shouldComponentUpdate(nextProps, nextState) { return nextProps.url !== this.props.url || nextProps.selected !== this.props.selected; } render() { const {props} = this; const selectedClass = props.selected === true ? "selected" : ""; var path = parseUri(props.url).path; path = path.length <= 0 ? props.url : "..." + path; return ( <li onMouseLeave={props.onMouseLeave} className={selectedClass}> <i className="ion-ios-eye" data-image={props.image} data-url={props.url} data-title={props.title} onClick={props.handlePlanetViewClick}/> <span onMouseEnter={props.onMouseEnter}> <div className="dot bg-mint"/> {path} </span> </li> ); } } ``` ### Related links: - [React Performance optimization](https://medium.com/@nesbtesh/react-performance-optimization-28ec5b61fff3) - [React rendering misconception](https://robots.thoughtbot.com/react-rendering-misconception) ================================================ FILE: perf-tips/02.pure-component.md ================================================ # Using Pure Components Pure Components do shallow equality checks in `shouldComponentUpdate` by default. This is intended to prevent renders when neither props nor state have changed. Recompose offers a Higher Order Component called `pure` for this purpose and React added `React.PureComponent` in v15.3.0. #### Bad ```javascript export default (props, context) => { // ... do expensive compute on props ... return <SomeComponent {...props} /> } ``` #### Good ```javascript import { pure } from 'recompose'; // This won't be called when the props DONT change export default pure((props, context) => { // ... do expensive compute on props ... return <SomeComponent someProp={props.someProp}/> }) ``` #### Better ```javascript // This is better mainly because it uses no external dependencies. import { PureComponent } from 'react'; export default class Example extends PureComponent { // This won't re-render when the props DONT change render() { // ... do expensive compute on props ... return <SomeComponent someProp={props.someProp}/> } } }) ``` ### Related links: - [Recompose](https://github.com/acdlite/recompose#composition) - [Higher Order Components with Functional Patterns Using Recompose](https://egghead.io/courses/higher-order-components-with-functional-patterns-using-recompose) - [React: PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent) - [Pure Components](https://www.fullstackreact.com/30-days-of-react/day-11/) - [Top 5 Recompose HOCs](https://medium.com/@abhiaiyer/top-5-recompose-hocs-1a4c9cc4566) ================================================ FILE: perf-tips/03.reselect.md ================================================ # Using reselect Use Reselect in Redux connect(mapState) -- to avoid frequent re-render. #### Bad ```javascript let App = ({otherData, resolution}) => ( <div> <DataContainer data={otherData}/> <ResolutionContainer resolution={resolution}/> </div> ); const doubleRes = (size) => ({ width: size.width * 2, height: size.height * 2 }); App = connect(state => { return { otherData: state.otherData, resolution: doubleRes(state.resolution) } })(App); ``` In this above case every time otherData in the state changes both DataContainer and ResolutionContainer will be rendered even when the resolution in the state does not change. This is because the doubleRes function will always return a new resolution object with a new identity. If doubleRes is written with Reselect the issue goes away: Reselect memoizes the last result of the function and returns it when called until new arguments are passed to it. #### Good ```javascript import { createSelector } from 'reselect'; const doubleRes = createSelector( r => r.width, r => r.height, (width, height) => ({ width: width * 2, height: height * 2 }) ); ``` ### Related links: - [React](https://medium.com/@esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#.cz2ypc2ob) - [Computing Derived Data: Docs](http://redux.js.org/docs/recipes/ComputingDerivedData.html) ================================================ FILE: perf-tips/README.md ================================================ # Perf Tips **Key Ideas** - Avoid Reconciliation with shouldComponentUpdate() check - Use Immutable Data Structures - Use Production Build - Profile Components with Chrome Timeline - Defer computationally expensive tasks in componentWillMount/componentDidMount by using setTimeout and/or requestAnimationFrame ## Articles [Optimizing Performance: Docs](https://reactjs.org/docs/optimizing-performance.html) [Performance Engineering with React](http://benchling.engineering/performance-engineering-with-react/) [Tips to optimise rendering of a set of elements in React](https://blog.lavrton.com/how-to-optimise-rendering-of-a-set-of-elements-in-react-ad01f5b161ae) [React.js Best Practices for 2016](https://blog.risingstack.com/react-js-best-practices-for-2016/) ================================================ FILE: styling/01.stateless-ui-components.md ================================================ # Styling in stateless UI components Keep styles separated from the parts of the app that are tied to state. That means routes, views, containers, forms, layouts, etc. should not have any styling or classes in them. Instead, these heavy-lifting components should be composed of primarily stateless functional UI components. Form component (with no styles/classNames) - just pure composed components ```javascript class SampleComponent extends Component { render() { return ( <form onSubmit={this.handleSubmit}> <Heading children='Sign In'/> <Input name='username' value={username} onChange={this.handleChange}/> <Input type='password' name='password' value={password} onChange={this.handleChange}/> <Button type='submit' children='Sign In'/> </form> ) } } // Presentational component (with Styles) const Button = ({ ...props }) => { const sx = { fontFamily: 'inherit', fontSize: 'inherit', fontWeight: 'bold', textDecoration: 'none', display: 'inline-block', margin: 0, paddingTop: 8, paddingBottom: 8, paddingLeft: 16, paddingRight: 16, border: 0, color: 'white', backgroundColor: 'blue', WebkitAppearance: 'none', MozAppearance: 'none' } return ( <button {...props} style={sx}/> ) } ``` ================================================ FILE: styling/02.styles-module.md ================================================ # Styles module Generally, hard coding styles values in a component should be avoided. Any values that are likely to be used across different UI components should be split into their own module. ```javascript // Styles module export const white = '#fff'; export const black = '#111'; export const blue = '#07c'; export const colors = { white, black, blue }; export const space = [ 0, 8, 16, 32, 64 ]; const styles = { bold: 600, space, colors }; export default styles ``` #### Usage ```javascript // button.jsx import React from 'react' import { bold, space, colors } from './styles' const Button = ({ ...props }) => { const sx = { fontFamily: 'inherit', fontSize: 'inherit', fontWeight: bold, textDecoration: 'none', display: 'inline-block', margin: 0, paddingTop: space[1], paddingBottom: space[1], paddingLeft: space[2], paddingRight: space[2], border: 0, color: colors.white, backgroundColor: colors.blue, WebkitAppearance: 'none', MozAppearance: 'none' }; return ( <button {...props} style={sx}/> ) }; ``` ================================================ FILE: styling/03.style-functions.md ================================================ # Style Functions Since we’re using JavaScript, we can also employ helper functions for styling elements. #### Example 1 A function to create rgba values of black ```javascript const darken = (n) => `rgba(0, 0, 0, ${n})`; darken(1 / 8); // 'rgba(0, 0, 0, 0.125)' const shade = [ darken(0), darken(1 / 8), darken(1 / 4), darken(3 / 8), darken(1 / 2), darken(5 / 8), darken(3 / 4), darken(7 / 8), darken(1) ]; // So now, // shade[4] is 'rgba(0, 0, 0, 0.5)' ``` #### Example 2 Creating a scale for margin and padding to help keep visual rhythm consistent ```javascript // Modular powers of two scale const scale = [ 0, 8, 16, 32, 64 ]; // Functions to get partial style objects const createScaledPropertyGetter = (scale) => (prop) => (x) => { return (typeof x === 'number' && typeof scale[x] === 'number') ? {[prop]: scale[x]} : null }; const getScaledProperty = createScaledPropertyGetter(scale); export const getMargin = getScaledProperty('margin'); export const getPadding = getScaledProperty('padding'); // Style function usage const Box = ({ m, p, ...props }) => { const sx = { ...getMargin(m), ...getPadding(p) }; return <div {...props} style={sx}/> }; // Component usage const Box = () => ( <div> <Box m={2} p={3}> A box with 16px margin and 32px padding </Box> </div> ); ``` ================================================ FILE: styling/04.using-npm-modules.md ================================================ # Using npm modules For more complex color/style transformation logic, it's always good to use it from a separate npm module (or) create one. #### Example For darkening scales in CSS you can use `chroma-js` module ```javascript import chroma from 'chroma-js' const alpha = (color) => (a) => chroma(color).alpha(a).css(); const darken = alpha('#000'); const shade = [ darken(0), darken(1 / 8), darken(1 / 4) // More... ]; const blueAlpha = [ alpha(blue)(0), alpha(blue)(1 / 4), alpha(blue)(1 / 2), alpha(blue)(3 / 4), alpha(blue)(1) ]; ``` ================================================ FILE: styling/05.base-component.md ================================================ # Base Component ### Using a Base Component There is tremendous amount of flexibility when it comes to composition in React – since components are essentially just functions. By changing style details in a component to props we can make it more reusable. The color and backgroundColor properties have been moved up to the component’s props. Additionally, we’ve added a big prop to adjust the padding top and bottom. ```javascript const Button = ({ big, color = colors.white, backgroundColor = colors.blue, ...props }) => { const sx = { fontFamily: 'inherit', fontSize: 'inherit', fontWeight: bold, textDecoration: 'none', display: 'inline-block', margin: 0, paddingTop: big ? space[2] : space[1], paddingBottom: big ? space[2] : space[1], paddingLeft: space[2], paddingRight: space[2], border: 0, color, backgroundColor, WebkitAppearance: 'none', MozAppearance: 'none' }; return ( <button {...props} style={sx}/> ) }; ``` #### Usage ```javascript const Button = () => ( <div> <Button> Blue Button </Button> <Button big backgroundColor={colors.red}> Big Red Button </Button> </div> ); // By adjusting the props API of the base Button component, // an entire set of button styles can be created. const ButtonBig = (props) => <Button {...props} big/>; const ButtonGreen = (props) => <Button {...props} backgroundColor={colors.green}/>; const ButtonRed = (props) => <Button {...props} backgroundColor={colors.red}/>; const ButtonOutline = (props) => <Button {...props} outline/>; ``` ================================================ FILE: styling/06.layout-component.md ================================================ # Layout component We can extend the idea of [Base components](./05.base-component.md) to create Layout components. #### Example ```javascript const Grid = (props) => ( <Box {...props} display='inline-block' verticalAlign='top' px={2}/> ); const Half = (props) => ( <Grid {...props} width={1 / 2}/> ); const Third = (props) => ( <Grid {...props} width={1 / 3}/> ); const Quarter = (props) => ( <Grid {...props} width={1 / 4}/> ); const Flex = (props) => ( <Box {...props} display='flex'/> ); const FlexAuto = (props) => ( <Box {...props} flex='1 1 auto'/> ); ``` #### Usage ```javascript const Layout = () => ( <div> <div> <Half>Half width column</Half> <Half>Half width column</Half> </div> <div> <Third>Third width column</Third> <Third>Third width column</Third> <Third>Third width column</Third> </div> <div> <Quarter>Quarter width column</Quarter> <Quarter>Quarter width column</Quarter> <Quarter>Quarter width column</Quarter> <Quarter>Quarter width column</Quarter> </div> </div> ); ``` ### Related links: - [Github: React Layout components](https://github.com/rofrischmann/react-layout-components) - [Leveling Up With React: Container Components](https://css-tricks.com/learning-react-container-components/) - [Container Components and Stateless Functional Components in React](Leveling Up With React: Container Components) ================================================ FILE: styling/07.typography-component.md ================================================ # Typography Component We can extend the idea of [Base components](./05.base-component.md) to create Typography components this pattern helps ensure consistency and keep your styling DRY. #### Example ```javascript import React from 'react'; import { alternateFont, typeScale, boldFontWeight } from './styles'; const Text = ({ tag = 'span', size = 4, alt, center, bold, caps, ...props }) => { const Tag = tag; const sx = { fontFamily: alt ? alternateFont : null, fontSize: typeScale[size], fontWeight: bold ? boldFontWeight : null, textAlign: center ? 'center' : null, textTransform: caps ? 'uppercase' : null }; return <Tag {...props} style={sx}/> }; const LeadText = (props) => <Text {...props} tag='p' size={3}/>; const Caps = (props) => <Text {...props} caps/>; const MetaText = (props) => <Text {...props} size={5} caps/>; const AltParagraph = (props) => <Text {...props} tag='p' alt/>; const CapsButton = ({ children, ...props }) => ( <Button {...props}> <Caps> {children} </Caps> </Button> ); ``` #### Usage ```javascript const TypographyComponent = () => ( <div> <LeadText> This is a lead with some<Caps>all caps</Caps>. It has a larger font size than the default paragraph. </LeadText> <MetaText> This is smaller text, like form helper copy. </MetaText> </div> ); ``` ================================================ FILE: styling/08.HOC-for-styling.md ================================================ # Using HOC for styling Sometimes there are isolated UI components that only require a minimal amount of state for interaction, and using them as standalone components is sufficient eg. Interactions in a Carousel #### Example: Carousel The HOC will have a current slide index and have previous and next methods. ```javascript // Higher order component import React from 'react' // This could be named something more generic like Counter or Cycle const CarouselContainer = (Comp) => { class Carousel extends React.Component { constructor() { super(); this.state = { index: 0 }; this.previous = () => { const { index } = this.state; if (index > 0) { this.setState({index: index - 1}) } }; this.next = () => { const { index } = this.state; this.setState({index: index + 1}) } } render() { return ( <Comp {...this.props} {...this.state} previous={this.previous} next={this.next}/> ) } } return Carousel }; export default CarouselContainer; ``` #### Using the HOC ```javascript // UI component const Carousel = ({ index, ...props }) => { const length = props.length || props.children.length || 0; const sx = { root: { overflow: 'hidden' }, inner: { whiteSpace: 'nowrap', height: '100%', transition: 'transform .2s ease-out', transform: `translateX(${index % length * -100}%)` }, child: { display: 'inline-block', verticalAlign: 'middle', whiteSpace: 'normal', outline: '1px solid red', width: '100%', height: '100%' } }; const children = React.Children.map(props.children, (child, i) => { return ( <div style={sx.child}> {child} </div> ) }); return ( <div style={sx.root}> <div style={sx.inner}> {children} </div> </div> ) }; // Final Carousel component const HeroCarousel = (props) => { return ( <div> <Carousel index={props.index}> <div>Slide one</div> <div>Slide two</div> <div>Slide three</div> </Carousel> <Button onClick={props.previous} children='Previous'/> <Button onClick={props.next} children='Next'/> </div> ) }; // Wrap the component with the functionality from the higher order component export default CarouselContainer(HeroCarousel) ``` By keeping the styling separate from the interactive state, any number of carousel variations can be created from these reusable parts. #### Usage ```javascript const Carousel = () => ( <div> <HeroCarousel /> </div> ); ``` ================================================ FILE: styling/README.md ================================================ # Styling in React Here we look into some ideas around using CSS in JS. If you are pondering over why to use CSS in JS, I highly recommend this [talk](http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html) by [Vjeux](https://twitter.com/Vjeux) ## Articles [Patterns for style composition in React](https://jxnblk.com/blog/patterns-for-style-composition-in-react/) [Inline style vs stylesheet performance](https://www.ctheu.com/2015/08/17/react-inline-styles-vs-css-stupid-benchmark/) ================================================ FILE: ux-variations/01.composing-variations.md ================================================ # Using Composition to handle UX variations Combining smaller reusable components to build a bigger UI blocks. **How do we make sure components are reusable?** - By ensuring our UI components are pure presentational components (dumb) **What does reusable mean?** - No data fetching within the component (do it in Redux). - If data is required from API - goes into Redux Via redux-thunk API calls are isolated away from the redux containers that deal with the data obtained and pass it on to the dumb component. If we have a bunch of renderBla() functions within the component which are used in the main component render() - It’s better to move it to separate components. That way it is reusable. ### Example Login page variations UX variations toggle features + add in additional links/markup. If the UX variations are involved toggling features within a component + adding minor markup around it ```javascript import React, { Component } from "react"; import PropTypes from 'prop-types'; import SignIn from "./sign-in"; class MemberSignIn extends Component { _renderMemberJoinLinks() { return ( <div className="member-signup-links"> ... </div> ); } _routeTo() { // Routing logic here } render() { const {forgotEmailRoute,forgotPwdRoute, showMemberSignupLinks} = this.props; return ( <div> <SignIn onForgotPasswordRequested={this._routeTo(forgotPwdRoute)} onForgotEmailRequested={this._routeTo(forgotEmailRoute)}> {this.props.children} {showMemberSignupLinks && this._renderMemberJoinLinks()} </SignIn> </div> ); } } export default MemberSignIn; ``` ### Related links: - [Slides from my talk: Building Multi-tenant UI with React](https://speakerdeck.com/vasa/building-multitenant-ui-with-react-dot-js) ================================================ FILE: ux-variations/02.toggle-ui-elements.md ================================================ # Toggle UI Elements Handling minor UX variations in the component by toggling ON/OFF features. Modify the component to take in a prop to control it’s behavior. ### Gotcha: Easy to overuse this idea by adding props for every variation. - Only add in props for features specific to the current feature that the component. - Basically, not violate the Single Responsibility Principle. #### Example Show/Hide password feature in Login form ```javascript class PasswordField extends Component { render() { const { password, showHidePassword, showErrorOnTop, showLabels, shouldComplyAda } = this.props; return ( <div> <Password field={password} label="Password" showErrorOnTop={showErrorOnTop} placeholder={shouldComplyAda ? "" : "Password"} showLabel={showLabels} showHidePassword={showHidePassword} /> </div> ); } } ``` ### Related links: - [Slides from my talk: Building Multi-tenant UI with React](https://speakerdeck.com/vasa/building-multitenant-ui-with-react-dot-js) ================================================ FILE: ux-variations/03.HOC-feature-toggles.md ================================================ # HOC for Feature Toggles Using Higher order components (HOC) for UX variations eg. Toggling features On/Off ```javascript // featureToggle.js const isFeatureOn = function (featureName) { // return true or false }; import { isFeatureOn } from './featureToggle'; const toggleOn = (featureName, ComposedComponent) => class HOC extends Component { render() { return isFeatureOn(featureName) ? <ComposedComponent {...this.props} /> : null; } }; // Usage import AdsComponent from './Ads' const Ads = toggleOn('ads', AdsComponent); ``` ================================================ FILE: ux-variations/04.HOC-props-proxy.md ================================================ # Higher Order Component - Props proxy This basically helps to add/edit props passed to the Component. ```javascript function HOC(WrappedComponent) { return class Test extends Component { render() { const newProps = { title: 'New Header', footer: false, showFeatureX: false, showFeatureY: true }; return <WrappedComponent {...this.props} {...newProps} /> } } } ``` ================================================ FILE: ux-variations/05.wrapper-components.md ================================================ # Wrapper Components Using Wrappers to handle UX/style variations For Handling Wrapper ``<div>``’s and other markup around component, use composition! When you create a React component instance, you can include additional React components or JavaScript expressions between the opening and closing tags. Parent can read its children by accessing the special this.props.children prop. ```javascript const SampleComponent = () => { <Parent> <Child /> </Parent> }; const Parent = () => { // You can use class 'bla' or any other classes to handle any style variations for the same markup. <div className="bla"> {this.props.children} </div> }; ``` FYI - Wrapper component can also be made accept a tag name and then used to generate the HTML element. However, usually this is not recommended because you can't add attributes/props to it. ```javascript const SampleComponent = () => { <Wrap tagName="div" content="Hello World" /> }; const Wrap = ({ tagName, content }) => { const Tag = `${tagName}` // variable name must begin with capital letters return <Tag>{content}</Tag> } ``` ### Related links: - [Slides from my talk: Building Multi-tenant UI with React](https://speakerdeck.com/vasa/building-multitenant-ui-with-react-dot-js) ================================================ FILE: ux-variations/06.display-order-variations.md ================================================ # Display UI elements in different order Use a prop to specify order – Map through ReactElements and render it based on order prop. ```javascript class PageSections extends Component { render() { const pageItems = this.props.contentOrder.map( (content) => { const renderFunc = this.contentOrderMap[content]; return (typeof renderFunc === 'function') ? renderFunc() : null; } ); return ( <div className="page-content"> {pageItems} </div> ) } } ``` ### Related links: - [Slides from my talk: Building Multi-tenant UI with React](https://speakerdeck.com/vasa/building-multitenant-ui-with-react-dot-js) ================================================ FILE: ux-variations/README.md ================================================ # Handling UX variations for multiple brands and apps ## [Slides from my talk](https://speakerdeck.com/vasa/building-multitenant-ui-with-react-dot-js) A few general coding principles which help write reusable React components ## Single Responsibility Principle **In React** Components/Containers code must essentially deal with only one chunk of the UI feature/functionality. * Eg. Shipping Address component * Address container (Only has address related fields), Name container (first and last name), Phone component, State, City and Zip code container **In Redux** All API related call go into Redux thunks/other async handling sections (redux-promise, sagas etc) * The thunks are responsible only for the dispatching action on AJAX begin/fail and complete. * Any routing has to be dealt with the receiving component via a promise. ## Keep it Simple Stupid (KISS) * Essentially, if the component needs no state - use stateless functions. * Perf matters: **Stateless fns > ES6 class components > React.createClass()** * Don’t pass any more props than required {...this.props} only if the list is big -- if not pass individual props. * Too much flows of control (If-else variations) inside the component is usually a red-flag. This most likely means - need to split up the component or create a separate variation. * Don’t optimize prematurely - Making the current component reusable with current variations known. ## Articles [Building React Components for Multiple Brands and Applications](https://medium.com/walmartlabs/building-react-components-for-multiple-brands-and-applications-7e9157a39db4)