Skip to content
This repository has been archived by the owner on Mar 31, 2021. It is now read-only.

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cassiozen committed Jan 23, 2016
0 parents commit b9e0938
Show file tree
Hide file tree
Showing 9 changed files with 481 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": [ "react", "es2015" ]
}
138 changes: 138 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
{
"parser": "babel-eslint",
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"comma-dangle": 0, // Disallow or enforce trailing commas
"no-cond-assign": 2, // Disallow assignment in conditional expressions
"no-constant-condition": 2, // Disallow use of constant expressions in conditions
"no-control-regex": 2, // Disallow control characters in regular expressions
"no-debugger": 2, // Disallow use of debugger
"no-dupe-args": 2, // Disallow duplicate arguments in functions
"no-dupe-keys": 2, // Disallow duplicate keys when creating object literals
"no-duplicate-case": 2, // Disallow a duplicate case label.
"no-empty": 2, // Disallow empty statements
"no-empty-character-class": 2, // Disallow the use of empty character classes in regular expressions
"no-ex-assign": 2, // Disallow assigning to the exception in a catch block
"no-extra-boolean-cast": 2, // Disallow double-negation boolean casts in a boolean context
"no-extra-parens": 0, // Disallow unnecessary parentheses (off by default)
"no-extra-semi": 2, // Disallow unnecessary semicolons
"no-func-assign": 2, // Disallow overwriting functions written as function declarations
"no-inner-declarations": 2, // Disallow function or variable declarations in nested blocks
"no-invalid-regexp": 2, // Disallow invalid regular expression strings in the RegExp constructor
"no-irregular-whitespace": 2, // Disallow irregular whitespace outside of strings and comments
"no-negated-in-lhs": 2, // Disallow negation of the left operand of an in expression
"no-obj-calls": 2, // Disallow the use of object properties of the global object (Math and JSON) as functions
"no-regex-spaces": 2, // Disallow multiple spaces in a regular expression literal
"no-reserved-keys": 0, // Disallow reserved words being used as object literal keys (off by default)
"no-sparse-arrays": 2, // Disallow sparse arrays
"no-unreachable": 2, // Disallow unreachable statements after a return, throw, continue, or break statement
"use-isnan": 2, // Disallow comparisons with the value NaN
"valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string


"consistent-return": 2, // Require return statements to either always or never specify values
"curly": 2, // Specify curly brace conventions for all control statements
"default-case": 2, // Require default case in switch statements (off by default)
"eqeqeq": 2, // Require the use of === and !==
"guard-for-in": 2, // Make sure for-in loops have an if statement (off by default)
"no-alert": 2, // Disallow the use of alert, confirm, and prompt
"no-caller": 2, // Disallow use of arguments.caller or arguments.callee
"no-div-regex": 2, // Disallow division operators explicitly at beginning of regular expression (off by default)
"no-empty-label": 2, // Disallow use of labels for anything other then loops and switches
"no-eval": 2, // Disallow use of eval()
"no-extend-native": 2, // Disallow adding to native types
"no-extra-bind": 2, // Disallow unnecessary function binding
"no-fallthrough": 2, // Disallow fallthrough of case statements
"no-floating-decimal": 2, // Disallow the use of leading or trailing decimal points in numeric literals (off by default)
"no-implied-eval": 2, // Disallow use of eval()-like methods
"no-iterator": 2, // Disallow usage of __iterator__ property
"no-labels": 2, // Disallow use of labeled statements
"no-lone-blocks": 2, // Disallow unnecessary nested blocks
"no-loop-func": 2, // Disallow creation of functions within loops
"no-multi-str": 2, // Disallow use of multiline strings
"no-multi-spaces": [0], // Disallow use of multiline strings
"no-native-reassign": 2, // Disallow reassignments of native objects
"no-new": 2, // Disallow use of new operator when not part of the assignment or comparison
"no-new-func": 2, // Disallow use of new operator for Function object
"no-new-wrappers": 2, // Disallows creating new instances of String,Number, and Boolean
"no-octal": 2, // Disallow use of octal literals
"no-octal-escape": 2, // Disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
"no-process-env": 2, // Disallow use of process.env (off by default)
"no-proto": 2, // Disallow usage of __proto__ property
"no-redeclare": 2, // Disallow declaring the same variable more then once
"no-return-assign": 2, // Disallow use of assignment in return statement
"no-script-url": 2, // Disallow use of javascript: urls.
"no-self-compare": 2, // Disallow comparisons where both sides are exactly the same (off by default)
"no-sequences": 2, // Disallow use of comma operator
"no-throw-literal": 2, // Restrict what can be thrown as an exception (off by default)
"no-void": 2, // Disallow use of void operator (off by default)
"no-with": 2, // Disallow use of the with statement
"radix": 2, // Require use of the second argument for parseInt() (off by default)
"wrap-iife": 2, // Require immediate function invocation to be wrapped in parentheses (off by default)
"yoda": 2, // Require or disallow Yoda conditions

"no-catch-shadow": 2, // Disallow the catch clause parameter name being the same as a variable in the outer scope
"no-delete-var": 2, // Disallow deletion of variables
"no-label-var": 2, // Disallow labels that share a name with a variable
"no-shadow": 0, // Disallow declaration of variables already declared in the outer scope
"no-shadow-restricted-names": 2, // Disallow shadowing of names such as arguments
"no-undef": 2, // Disallow use of undeclared variables unless mentioned in a /*global */ block
"no-undef-init": 2, // Disallow use of undefined when initializing variables
"no-unused-vars": 2, // Disallow declaration of variables that are not used in the code
"no-use-before-define": 0,

"indent": [1, 2], // This option sets a specific tab width for your code (off by default)
"brace-style": 1, // Enforce one true brace style (off by default)
"camelcase": 1, // Require camel case names
"comma-spacing": [1, {"before": false, "after": true}], // enforce spacing before and after comma
"comma-style": [1, "last"], // Enforce one true comma style (off by default)
"consistent-this": [1, "_this"], // Enforces consistent naming when capturing the current execution context (off by default)
"eol-last": 1, // Enforce newline at the end of file, with no multiple empty lines
"func-names": 0, // Require function expressions to have a name (off by default)
"func-style": 0, // Enforces use of function declarations or expressions (off by default)
"key-spacing": [1, {"beforeColon": false, "afterColon": true}], // enforces spacing between keys and values in object literal properties
"max-nested-callbacks": [1, 3], // Specify the maximum depth callbacks can be nested (off by default)
"new-cap": [1, {newIsCap: true, capIsNew: false}], // require a capital letter for constructors
"new-parens": 1, // Disallow the omission of parentheses when invoking a constructor with no arguments
"newline-after-var": 0, // Allow/disallow an empty newline after var statement (off by default)
"no-array-constructor": 1, // Disallow use of the Array constructor
"no-inline-comments": 0, // Disallow comments inline after code (off by default)
"no-lonely-if": 1, // Disallow if as the only statement in an else block (off by default)
"no-mixed-spaces-and-tabs": 1, // Disallow mixed spaces and tabs for indentation
"no-multiple-empty-lines": [1, {"max": 2}], // disallow multiple empty lines (off by default)
"no-nested-ternary": 1, // Disallow nested ternary expressions (off by default)
"no-new-object": 1, // Disallow use of the Object constructor
"no-spaced-func": 1, // Disallow space between function identifier and application
"no-ternary": 0, // Disallow the use of ternary operators (off by default)
"no-trailing-spaces": 1, // Disallow trailing whitespace at the end of lines
"no-underscore-dangle": 0, // Disallow dangling underscores in identifiers
"one-var": [1, "never"], // Allow just one var statement per function (off by default)
"operator-assignment": [1, "never"], // Require assignment operator shorthand where possible or prohibit it entirely (off by default)
"padded-blocks": [0, "never"], // Enforce padding within blocks (off by default)
"quote-props": [1, "as-needed"], // Require quotes around object literal property names (off by default)
"quotes": [1, "single"], // Specify whether double or single quotes should be used
"semi": [1, "always"], // Require or disallow use of semicolons instead of ASI
"semi-spacing": [1, {"before": false, "after": true}], // enforce spacing before and after semicolons
"space-before-blocks": [1, "always"], // Require or disallow space before blocks (off by default)
"space-in-brackets": [0, "never"], // Require or disallow spaces inside brackets (off by default)
"space-in-parens": [1, "never"], // Require or disallow spaces inside parentheses (off by default)
"space-infix-ops": [1, {}], // Require spaces around operators
"space-return-throw-case": [1], // require a space after return, throw, and case
"space-unary-ops": [1, {"words": true, "nonwords": false}], // Require or disallow spaces before/after unary operators (words on by default, nonwords off by default)
"spaced-comment": [1, "always"], // Require or disallow a space immediately following the // in a line comment (off by default)
"wrap-regex": 0, // Require regex literals to be wrapped in parentheses (off by default)

"no-var": 2, // Require let or const instead of var (off by default)

"max-depth": [2, 3], // Specify the maximum depth that blocks can be nested (off by default)
"max-len": [2, 100, 2], // Specify the maximum length of a line in your program (off by default)
"max-params": [2, 5], // Limits the number of parameters that can be used in the function declaration. (off by default)
"max-statements": 0, // Specify the maximum number of statement allowed in a function (off by default)
"no-bitwise": 0, // Disallow use of bitwise operators (off by default)
"no-plusplus": 0 // Disallow use of unary operators, ++ and -- (off by default)
}
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
npm-debug.log
.DS_Store
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
React Class autoBind
=====================

Automatically binds methods defined within a component's Class to the current object's lexical `this` instance (similarly to the default behavior of React.createClass).


### Description

React 0.13 introduced the possibility to define components using plain JavaScript ES6 classes. But differently from the traditional React.createClass, user defined methods in a ES6 class are not automatically bound.

Autobind is an utility function that can be called from the class constructor to bind the class methods to the component instance.

### Installation

To install the stable version:

```
npm install --save react-autobind
```

### Usage
You will generally call autoBind from the class constructor, passing the 'this' context:

```
constructor() {
super();
autoBind(this);
}
```

Autobind is smart enough to avoid binding React related methods (such as render and lifecycle hooks).

You can also explicitly specify which methods you want to bind:

```
constructor() {
super();
autoBind(this, 'myMethod1', 'myMethod2');
}
```

### Example

```
import React from 'react';
import {render} from 'react-dom';
import autoBind from './autoBind';
class App extends React.Component {
constructor() {
super();
this.state = {
clickCounter: 0
}
autoBind(this);
}
componentDidMount() {
console.log("Component is mounted");
}
increment() {
this.setState({
clickCounter: this.state.clickCounter + 1
});
}
render(){
return (
<div>
<h1>Number of clicks: {this.state.clickCounter}</h1>
<button onClick={this.increment}>Increment Counter</button>
</div>
);
}
}
render(<App />, document.getElementById('root'));
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib/autoBind');
65 changes: 65 additions & 0 deletions lib/autoBind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

Object.defineProperty(exports, '__esModule', {
value: true
});
exports['default'] = autoBind;
var wontBind = ['constructor', 'render', 'componentWillMount', 'componentDidMount', 'componentWillReceiveProps', 'shouldComponentUpdate', 'componentWillUpdate', 'componentDidUpdate', 'componentWillUnmount'];

var toBind = [];

function autoBind(context) {
if (context === undefined) {
'console' in window && console.error('Autobind error: No context provided.');
return;
}

var objPrototype = Object.getPrototypeOf(context);

if (arguments.length > 1) {
// If a list of methods to bind is provided, use it.
toBind = Array.prototype.slice.call(arguments, 1);
} else {
// If no list of methods to bind is provided, bind all available methods in class.
toBind = Object.getOwnPropertyNames(objPrototype);
}

toBind.forEach(function (method) {
var descriptor = Object.getOwnPropertyDescriptor(objPrototype, method);

// Return if it's special case function or if not a function at all
if (wontBind.indexOf(method) !== -1 || typeof descriptor.value !== 'function') {
return;
}

Object.defineProperty(objPrototype, method, boundMethod(objPrototype, method, descriptor));
});
}

/**
* From autobind-decorator (https://github.com/andreypopp/autobind-decorator/tree/master)
* Return a descriptor removing the value and returning a getter
* The getter will return a .bind version of the function
* and memoize the result against a symbol on the instance
*/
function boundMethod(objPrototype, method, descriptor) {
var fn = descriptor.value;

return {
configurable: true,
get: function get() {
if (this === objPrototype || this.hasOwnProperty(method)) {
return fn;
}

var boundFn = fn.bind(this);
Object.defineProperty(this, method, {
value: boundFn,
configurable: true,
writable: true
});
return boundFn;
}
};
}
module.exports = exports['default'];
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "react-autobind",
"version": "1.0.0",
"description": "Automatically binds methods defined within a component's Class to the current object's lexical `this` instance (similarly to the default behavior of React.createClass).",
"main": "index.js",
"scripts": {
"test": "mocha --require babel-core/register"
},
"author": "Cássio M. Antonio",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/cassiozen/React-autobind.git"
},
"devDependencies": {
"babel-core": "~6.0.*",
"babel-loader": "~6.0.*",
"babel-preset-es2015": "~6.0.*",
"babel-preset-react": "~6.0.*",
"mocha": "^2.3.0"
}
}
68 changes: 68 additions & 0 deletions src/autoBind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const wontBind = [
'constructor',
'render',
'componentWillMount',
'componentDidMount',
'componentWillReceiveProps',
'shouldComponentUpdate',
'componentWillUpdate',
'componentDidUpdate',
'componentWillUnmount'
];

let toBind = [];

export default function autoBind (context) {
if(context === undefined) {
'console' in window && console.error('Autobind error: No context provided.');
return;
}

let objPrototype = Object.getPrototypeOf(context);

if(arguments.length > 1) {
// If a list of methods to bind is provided, use it.
toBind = Array.prototype.slice.call(arguments, 1);
} else {
// If no list of methods to bind is provided, bind all available methods in class.
toBind = Object.getOwnPropertyNames(objPrototype);
}

toBind.forEach(function(method) {
let descriptor = Object.getOwnPropertyDescriptor(objPrototype, method);

// Return if it's special case function or if not a function at all
if(wontBind.indexOf(method) !== -1 || typeof descriptor.value !== 'function') {
return;
}

Object.defineProperty(objPrototype, method, boundMethod(objPrototype, method, descriptor));
});
}

/**
* From autobind-decorator (https://github.com/andreypopp/autobind-decorator/tree/master)
* Return a descriptor removing the value and returning a getter
* The getter will return a .bind version of the function
* and memoize the result against a symbol on the instance
*/
function boundMethod(objPrototype, method, descriptor) {
let fn = descriptor.value;

return {
configurable: true,
get() {
if (this === objPrototype || this.hasOwnProperty(method)) {
return fn;
}

let boundFn = fn.bind(this);
Object.defineProperty(this, method, {
value: boundFn,
configurable: true,
writable: true
});
return boundFn;
}
};
}
Loading

0 comments on commit b9e0938

Please sign in to comment.