├── README.md ├── index.js ├── package.json └── src └── index.jsx /README.md: -------------------------------------------------------------------------------- 1 | # React Pure Component 2 | Mixins are no longer usable in es6, es7 land. So we can not use pure render mixin in classes. Higher Order Components can help us mitigate this problem. 3 | 4 | - [Mixins are dead]( https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750) 5 | - [React Mixins are on their way out](https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#mixins) 6 | 7 | > Unfortunately, we will not launch any mixin support for ES6 classes in React. That would defeat the purpose of only using idiomatic JavaScript concepts. 8 | > There is no standard and universal way to define mixins in JavaScript. In fact, several features to support mixins were dropped from ES6 today. There are a lot of libraries with different semantics. We think that there should be one way of defining mixins that you can use for any JavaScript class. React just making another doesn’t help that effort. 9 | 10 | - [Composition to the rescue](https://github.com/facebook/react/issues/1380#issue-31121026) 11 | 12 | > To be clear, mixins is an escape hatch to work around reusability limitations in the system. It’s not idiomatic React. Making composition easier is a higher priority than making arbitrary mixins work. I’ll focus on making composition easier so we can get rid of mixins. 13 | 14 | ## Installation 15 | ```bash 16 | npm i react.pure.component --save 17 | ``` 18 | 19 | ### es7 20 | ```js 21 | import {Component} from 'react'; 22 | import PureComponent from 'react.pure.component'; 23 | 24 | @PureComponent 25 | class App extends Component { 26 | render() { 27 | return ( 28 |
Hello Pure World
29 | ); 30 | } 31 | } 32 | 33 | export default App; 34 | ``` 35 | 36 | ### es6 37 | ```js 38 | import {Component} from 'react'; 39 | import PureComponent from 'react.pure.component'; 40 | 41 | class App extends Component { 42 | render() { 43 | return ( 44 |
Hello Pure World
45 | ); 46 | } 47 | } 48 | 49 | export default PureComponent(App); 50 | ``` 51 | 52 | ### es5 53 | ```js 54 | const React = require('react'); 55 | import PureComponent from 'react.pure.component'; 56 | 57 | const App = React.createClass({ 58 | render() { 59 | return ( 60 |
Hello Pure World
61 | ); 62 | } 63 | }) 64 | 65 | module.exports = PureComponent(App); 66 | ``` 67 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 10 | 11 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 12 | 13 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 14 | 15 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 16 | 17 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 18 | 19 | var _reactAddonsShallowCompare = require("react-addons-shallow-compare"); 20 | 21 | var _reactAddonsShallowCompare2 = _interopRequireDefault(_reactAddonsShallowCompare); 22 | 23 | var _react = require("react"); 24 | 25 | var _react2 = _interopRequireDefault(_react); 26 | 27 | exports["default"] = function (DecoratedComponent) { 28 | return (function (_Component) { 29 | _inherits(PureComponent, _Component); 30 | 31 | function PureComponent() { 32 | _classCallCheck(this, PureComponent); 33 | 34 | _get(Object.getPrototypeOf(PureComponent.prototype), "constructor", this).apply(this, arguments); 35 | } 36 | 37 | _createClass(PureComponent, [{ 38 | key: "shouldComponentUpdate", 39 | 40 | /** 41 | * Tells if a component should update given it's next props 42 | * and state. 43 | * 44 | * @param nextProps Next props. 45 | * @param nextState Next state. 46 | */ 47 | value: function shouldComponentUpdate(nextProps, nextState) { 48 | return (0, _reactAddonsShallowCompare2["default"])(this, nextProps, nextState); 49 | } 50 | }, { 51 | key: "render", 52 | value: function render() { 53 | return _react2["default"].createElement(DecoratedComponent, _extends({}, this.props, this.state)); 54 | } 55 | }]); 56 | 57 | return PureComponent; 58 | })(_react.Component); 59 | }; 60 | 61 | module.exports = exports["default"]; 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react.pure.component", 3 | "version": "1.2.0", 4 | "description": "React es6, es7 pure component without purerender mixin", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nadimtuhin/react-pure-component.git" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "pure-render", 16 | "es6", 17 | "es7", 18 | "decorators", 19 | "mixins" 20 | ], 21 | "author": "Nadim Tuhin (http://nadimtuhin.com)", 22 | "license": "ISC", 23 | "bugs": { 24 | "url": "https://github.com/nadimtuhin/react-pure-component/issues" 25 | }, 26 | "dependencies": { 27 | "react-addons-shallow-compare": "^15.3.2" 28 | }, 29 | "homepage": "https://github.com/nadimtuhin/react-pure-component#readme" 30 | } 31 | -------------------------------------------------------------------------------- /src/index.jsx: -------------------------------------------------------------------------------- 1 | import shallowCompare from "react-addons-shallow-compare"; 2 | import React, {Component} from "react"; 3 | 4 | export default function (DecoratedComponent) { 5 | return class PureComponent extends Component { 6 | /** 7 | * Tells if a component should update given it's next props 8 | * and state. 9 | * 10 | * @param nextProps Next props. 11 | * @param nextState Next state. 12 | */ 13 | shouldComponentUpdate(nextProps, nextState) { 14 | return shallowCompare(this, nextProps, nextState); 15 | } 16 | 17 | render() { 18 | return ; 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------