├── .babelrc ├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── package.json ├── scripts └── build └── src ├── component.js ├── function.js ├── index.js ├── mixin.js └── shallowEqual.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "stage": 0, 3 | "loose": ["es6.modules", "es6.classes"] 4 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "mocha": true 6 | }, 7 | "parser": "babel-eslint", 8 | "rules": { 9 | "quotes": [2, "single"], 10 | "eol-last": [0], 11 | "no-mixed-requires": [0], 12 | "no-underscore-dangle": [0], 13 | "consistent-return": [0], 14 | "strict": [0, "never"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | 4 | # Build products 5 | component.js 6 | function.js 7 | index.js 8 | mixin.js 9 | shallowEqual.js -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | scripts -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dan Abramov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # No Maintenance Intended 2 | 3 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 | 5 | 6 | 7 | This project is no longer actively maintained. It does its job, but there are no plans to extend or change it. 8 | We suggest you to use the official [`react-addons-shallow-compare`](https://facebook.github.io/react/docs/shallow-compare.html) package instead which does the same job. To wrap functional components in a more expressive way, we encourage you to check out [`recompose`](https://github.com/acdlite/recompose#optimize-rendering-performance). 9 | 10 | 11 | # react-pure-render 12 | 13 | A function, a component and a mixin for React pure rendering. 14 | 15 | This module provides *exactly* the same functionality as [PureRenderMixin](https://facebook.github.io/react/docs/pure-render-mixin.html), but as a standalone module and in three different flavors. 16 | 17 | ### Usage 18 | 19 | #### Function 20 | 21 | This is my preferred method, but it requires ES7 [class property transform](https://gist.github.com/jeffmo/054df782c05639da2adb) to be enabled by putting `{ "stage": 0 }` in your [.babelrc](https://babeljs.io/docs/usage/babelrc/). 22 | 23 | ```js 24 | import { Component } from 'react'; 25 | import shouldPureComponentUpdate from 'react-pure-render/function'; 26 | 27 | export default class Button extends Component { 28 | shouldComponentUpdate = shouldPureComponentUpdate; 29 | 30 | render() { } 31 | } 32 | ``` 33 | 34 | #### Component 35 | 36 | Inheritance is not very cool but it doesn't hurt a lot if it's just for the sake of this single method. If you don't want to use stage 0 transforms, you can use a base class instead: 37 | 38 | ```js 39 | import PureComponent from 'react-pure-render/component'; 40 | 41 | export default class Button extends PureComponent { 42 | render() { } 43 | } 44 | ``` 45 | 46 | #### Mixin 47 | 48 | If you're working with `createClass`-style components, use the mixin. It's exactly the same as [`React.addons.PureRenderMixin`](https://facebook.github.io/react/docs/pure-render-mixin.html). 49 | 50 | ```js 51 | var React = require('react'); 52 | var PureMixin = require('react-pure-render/mixin'); 53 | 54 | var Button = React.createClass({ 55 | mixins: [PureMixin], 56 | 57 | render: function () { } 58 | }); 59 | 60 | module.exports = Button; 61 | ``` 62 | 63 | #### shallowEqual 64 | 65 | Sometimes `shallowEqual` is all you need. It's bad to reach out into React internals, so this library exposes exactly the same `shallowEqual` you already know and love from React. 66 | 67 | ```js 68 | import shallowEqual from 'react-pure-render/shallowEqual'; 69 | console.log(shallowEqual({ x: 42 }, { x: 42 })); 70 | ``` 71 | 72 | ### Known Issues 73 | 74 | If a component in the middle of your rendering chain has pure rendering, but some nested component relies on a `context` change up the tree, **the nested component won't learn about `context` change and won't update**. This is a [known React issue](https://github.com/facebook/react/issues/2517) that exists because `context` is an [experimental](https://facebook.github.io/react/docs/context.html) feature and is not finished. However some React libraries already rely on `context`, for example, [React Router](https://github.com/rackt/react-router). My suggestion for now is to use pure components in apps relying on such libraries very carefully, and only use pure rendering for leaf-ish components that are known *not* to rely on any parent `context`. 75 | 76 | ### Further Reading 77 | 78 | * [PureRenderMixin](https://facebook.github.io/react/docs/pure-render-mixin.html) 79 | * [Advanced Performance](https://facebook.github.io/react/docs/advanced-performance.html) 80 | 81 | ### License 82 | 83 | MIT 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-pure-render", 3 | "version": "1.0.2", 4 | "description": "A function, a component and a mixin for React pure rendering", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/gaearon/react-pure-render.git" 9 | }, 10 | "scripts": { 11 | "build": "./scripts/build", 12 | "prepublish": "npm run build" 13 | }, 14 | "keywords": [ 15 | "react", 16 | "pure", 17 | "render", 18 | "shouldComponentUpdate", 19 | "optimization", 20 | "performance" 21 | ], 22 | "author": "Dan Abramov (http://github.com/gaearon)", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/gaearon/react-pure-render/issues" 26 | }, 27 | "homepage": "https://github.com/gaearon/react-pure-render", 28 | "devDependencies": { 29 | "babel": "^5.2.9", 30 | "babel-eslint": "^3.0.1", 31 | "eslint": "^0.20.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./node_modules/.bin/babel src --out-dir . -------------------------------------------------------------------------------- /src/component.js: -------------------------------------------------------------------------------- 1 | import shouldPureComponentUpdate from './function'; 2 | import { Component } from 'react'; 3 | 4 | export default class PureComponent extends Component {} 5 | PureComponent.prototype.shouldComponentUpdate = shouldPureComponentUpdate; 6 | -------------------------------------------------------------------------------- /src/function.js: -------------------------------------------------------------------------------- 1 | import shallowEqual from './shallowEqual'; 2 | 3 | export default function shouldPureComponentUpdate(nextProps, nextState) { 4 | return !shallowEqual(this.props, nextProps) || 5 | !shallowEqual(this.state, nextState); 6 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export shallowEqual from './shallowEqual'; 2 | export shouldPureComponentUpdate from './function'; 3 | export PureComponent from './component'; 4 | export PureMixin from './mixin'; -------------------------------------------------------------------------------- /src/mixin.js: -------------------------------------------------------------------------------- 1 | import shouldPureComponentUpdate from './function'; 2 | 3 | export default { 4 | shouldComponentUpdate: shouldPureComponentUpdate 5 | }; -------------------------------------------------------------------------------- /src/shallowEqual.js: -------------------------------------------------------------------------------- 1 | export default function shallowEqual(objA, objB) { 2 | if (objA === objB) { 3 | return true; 4 | } 5 | 6 | if (typeof objA !== 'object' || objA === null || 7 | typeof objB !== 'object' || objB === null) { 8 | return false; 9 | } 10 | 11 | var keysA = Object.keys(objA); 12 | var keysB = Object.keys(objB); 13 | 14 | if (keysA.length !== keysB.length) { 15 | return false; 16 | } 17 | 18 | // Test for A's keys different from B. 19 | var bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB); 20 | for (var i = 0; i < keysA.length; i++) { 21 | if (!bHasOwnProperty(keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { 22 | return false; 23 | } 24 | } 25 | 26 | return true; 27 | } --------------------------------------------------------------------------------