Skip to content

Commit 096120f

Browse files
authoredJun 21, 2019
Merge pull request #13 from lake-effect/master
Added @lock
2 parents d908916 + a7322bd commit 096120f

File tree

8 files changed

+169
-31
lines changed

8 files changed

+169
-31
lines changed
 

‎README.md

+37-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
# react-decoration
22

3-
[![Build Status](https://travis-ci.org/mbasso/react-decoration.svg?branch=master)](https://travis-ci.org/mbasso/react-decoration)
4-
[![npm version](https://img.shields.io/npm/v/react-decoration.svg)](https://www.npmjs.com/package/react-decoration)
5-
[![npm downloads](https://img.shields.io/npm/dm/react-decoration.svg?maxAge=2592000)](https://www.npmjs.com/package/react-decoration)
6-
[![Coverage Status](https://coveralls.io/repos/github/mbasso/react-decoration/badge.svg?branch=master)](https://coveralls.io/github/mbasso/react-decoration?branch=master)
7-
[![Join the chat at https://gitter.im/mbasso/react-decoration](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mbasso/react-decoration?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
3+
[![Build
4+
Status](https://travis-ci.org/mbasso/react-decoration.svg?branch=master)](https://travis-ci.org/mbasso/react-decoration)
5+
[![npm
6+
version](https://img.shields.io/npm/v/react-decoration.svg)](https://www.npmjs.com/package/react-decoration)
7+
[![npm
8+
downloads](https://img.shields.io/npm/dm/react-decoration.svg?maxAge=2592000)](https://www.npmjs.com/package/react-decoration)
9+
[![Coverage
10+
Status](https://coveralls.io/repos/github/mbasso/react-decoration/badge.svg?branch=master)](https://coveralls.io/github/mbasso/react-decoration?branch=master)
11+
[![Join the chat at
12+
https://gitter.im/mbasso/react-decoration](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mbasso/react-decoration?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
813

914
> A collection of @decorators for React Components
1015
1116
- - -
1217

13-
**Attention - In order to use react-decoration you have to use babel 5 or use [this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) plugin for babel 6. Check [this](https://github.com/mbasso/react-decoration/blob/master/docs/Introduction.md) page for information.**
18+
**Attention - In order to use react-decoration you have to use babel 5
19+
or use
20+
[this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy)
21+
plugin for babel 6. Check
22+
[this](https://github.com/mbasso/react-decoration/blob/master/docs/Introduction.md)
23+
page for information.**
1424

1525
- - -
1626

@@ -22,11 +32,15 @@ You can install react-decoration using [npm](https://www.npmjs.com/package/react
2232
npm install --save react-decoration
2333
```
2434

25-
If you aren't using npm in your project, you can include reactDecoration using UMD build in the dist folder with `<script>` tag.
35+
If you aren't using npm in your project, you can include
36+
reactDecoration using UMD build in the dist folder with `<script>`
37+
tag.
2638

2739
## Usage
2840

29-
Once you have installed react-decoration, supposing a CommonJS environment, you can import decorators in this way and immediately use them with no configuration.
41+
Once you have installed react-decoration, supposing a CommonJS
42+
environment, you can import decorators in this way and immediately use
43+
them with no configuration.
3044

3145
```js
3246
import React from 'react';
@@ -100,19 +114,30 @@ class SampleForm extends React.Component {
100114

101115
## Documentation
102116

103-
Visit [docs](https://github.com/mbasso/react-decoration/blob/master/docs) folder to find the complete list of decorators and their usage.
117+
Visit
118+
[docs](https://github.com/mbasso/react-decoration/blob/master/docs)
119+
folder to find the complete list of decorators and their usage.
104120

105121
## Change Log
106122

107-
This project adheres to [Semantic Versioning](http://semver.org/).
108-
Every release, along with the migration instructions, is documented on the Github [Releases](https://github.com/mbasso/react-decoration/releases) page.
123+
This project adheres to [Semantic Versioning](http://semver.org/).
124+
Every upstream release, along with the migration instructions, is
125+
documented on the Github
126+
[Releases](https://github.com/mbasso/react-decoration/releases) page.
109127

110128
## Authors
129+
111130
**Matteo Basso**
112131
- [github/mbasso](https://github.com/mbasso)
113132
- [@Teo_Basso](https://twitter.com/Teo_Basso)
114133

134+
**Ashley Lake**
135+
- [gitlab/lake_effect](https://gitlab.com/lake_effect)
136+
- [Ashley Lake](ashelake@protonmail.com)
137+
115138
## Copyright and License
139+
116140
Copyright (c) 2016, Matteo Basso.
117141

118-
react-decoration source code is licensed under the [MIT License](https://github.com/mbasso/react-decoration/blob/master/LICENSE.md).
142+
react-decoration source code is licensed under the [MIT
143+
License](https://github.com/mbasso/react-decoration/blob/master/LICENSE.md).

‎docs/Introduction.md

+38-18
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,69 @@
11
## Introduction
22

3-
As we said in [README](https://github.com/mbasso/react-decoration/blob/master/README.md) file, in order to use [react-decoration](https://github.com/mbasso/react-decoration) you have to use babel 5 or [this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) plugin for babel 6. This allows you to compile decorators in the right way, so you can use them.
4-
Note that this is not an official babel plugin but, as we can see [here](http://babeljs.io/docs/plugins/transform-decorators/) this is the only way to parse decorators at the moment:
3+
As we said in
4+
[README](https://github.com/mbasso/react-decoration/blob/master/README.md)
5+
file, in order to use
6+
[react-decoration](https://github.com/mbasso/react-decoration) you
7+
have to use babel 5 or
8+
[this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy)
9+
plugin for babel 6. This allows you to compile decorators in the right
10+
way, so you can use them. Note that this is not an official babel
11+
plugin but, as we can see
12+
[here](http://babeljs.io/docs/plugins/transform-decorators/) this is
13+
the only way to parse decorators at the moment:
514

6-
> Decorators are disabled in Babel v6, pending a proposal update – see [babel/babel#2645](https://github.com/babel/babel/issues/2645).
7-
>
8-
> Until Babel officially supports decorators again, you might want to try the third-party [transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) plugin, or use Babel v5.
15+
> Decorators are disabled in Babel v6, pending a proposal update – see
16+
> [babel/babel#2645](https://github.com/babel/babel/issues/2645).
17+
>
18+
> Until Babel officially supports decorators again, you might want to
19+
> try the third-party
20+
> [transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy)
21+
> plugin, or use Babel v5.
922
10-
Here is a quick installation guide from [transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy):
23+
Here is a quick installation guide from
24+
[transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy):
1125

1226
> ## Installation & Usage
13-
>
27+
>
1428
> ```bash
1529
> npm install --save-dev babel-plugin-transform-decorators-legacy
1630
> ```
17-
>
31+
>
1832
> Add the following line to your .babelrc file:
19-
>
33+
>
2034
> ```js
2135
> {
2236
> "plugins": ["transform-decorators-legacy"]
2337
> }
2438
> ```
25-
>
39+
>
2640
> #### NOTE: Order of Plugins Matters!
2741
> If you are including your plugins manually and using `transform-class-properties`, make sure that `transform-decorators-legacy` comes *before* `transform-class-properties`.
28-
>
42+
>
2943
> ```js
3044
> /// WRONG
31-
>
45+
>
3246
> "plugins": [
3347
> "transform-class-properties",
3448
> "transform-decorators-legacy"
3549
> ]
36-
>
50+
>
3751
> // RIGHT
38-
>
52+
>
3953
> "plugins": [
4054
> "transform-decorators-legacy",
4155
> "transform-class-properties"
4256
> ]
4357
> ```
4458
45-
Subsequently to this, you should read [this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy#best-effort)
46-
specification. In this way you will be able to avoid a series of problems that can take a lot of time to resolve.
59+
Subsequently to this, you should read
60+
[this](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy#best-effort)
61+
specification. In this way you will be able to avoid a series of
62+
problems that can take a lot of time to resolve.
4763
48-
Please note that react-decoration does not include polyfill, so, if you want to support old browsers, you have to emulate `Object.setPrototypeOf` and `Object.assign`.
64+
Please note that react-decoration does not include polyfill, so, if
65+
you want to support old browsers, you have to emulate
66+
`Object.setPrototypeOf` and `Object.assign`.
4967
5068
Consider also that decorators can be imported in 2 different ways:
5169
@@ -56,4 +74,6 @@ import { throttle } from 'react-decoration';
5674
import throttle from 'react-decoration/lib/decorators/functions/throttle';
5775
```
5876
59-
Importing each decorator from its file is suggested, importing a single decorator from react-decoration, infact, causes the import of all modules, that increase the bundle size.
77+
Importing each decorator from its file is suggested, importing a
78+
single decorator from react-decoration, infact, causes the import of
79+
all modules, that increase the bundle size.

‎docs/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Here you can find the complete list of decorators, however we encourage you to r
2828
- [`@injectProps`](functions/injectProps.md)
2929
- [`@injectState`](functions/injectState.md)
3030
- [`@debounce(wait: number = 300, immediate: boolean = false)`](functions/debounce.md)
31+
- [`@lock`](functions/lock.md)
3132
- [`@throttle(wait: number = 300, options: Object = { leading: true, trailing: true })`](functions/throttle.md)
3233
- [`@trace`](functions/trace.md)
3334
- [`@time(label: string)`](functions/time.md)

‎docs/functions/lock.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
## @lock
2+
3+
Executes the decorated function as soon as you call it for the first
4+
time, and then disables further execution.
5+
6+
#### Example
7+
8+
```js
9+
class Button extends React.Component {
10+
11+
@lock
12+
onClick(e) {
13+
// supposing that a user is clicking repeatedly the button
14+
// this function executes only once, immediately, because the event handler
15+
// is then redefined to `null`
16+
17+
console.log('Clicked!');
18+
}
19+
20+
render() {
21+
return (
22+
<input
23+
type="button"
24+
onClick={this.onClick}
25+
{...this.props}
26+
/>
27+
);
28+
}
29+
}
30+
```

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-decoration",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"description": "A collection of @decorators for React Components",
55
"main": "lib/index.js",
66
"jsnext:main": "es/index.js",

‎src/decorators/functions/lock.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { validateFunction } from '../../utils/validators';
2+
3+
export default function lock(target, key, descriptor) {
4+
let userFunc = descriptor.value;
5+
6+
validateFunction(userFunc, 'lock');
7+
8+
return {
9+
...descriptor,
10+
value: function locker(...params) {
11+
if (userFunc) {
12+
// Call the result immediately, but then set the function to
13+
// null so it cannot be called again
14+
userFunc.apply(this, [...params]);
15+
userFunc = null;
16+
}
17+
},
18+
};
19+
}

‎src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export extractValue from './decorators/events/extractValue';
3030
export extractNativeEvent from './decorators/events/extractNativeEvent';
3131
export extractDataset from './decorators/events/extractDataset';
3232
export autobind from './decorators/functions/autobind';
33+
export lock from './decorators/functions/lock';
3334
export log from './decorators/functions/log';
3435
export inject from './decorators/functions/inject';
3536
export injectProps from './decorators/functions/injectProps';

‎test/functions.spec.js

+42
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
injectProps,
1010
injectState,
1111
debounce,
12+
lock,
1213
throttle,
1314
trace,
1415
time,
@@ -206,6 +207,47 @@ describe('functions', () => {
206207
simulateTextInput(LeadingEdgeInput);
207208
});
208209

210+
it('lock', (done) => {
211+
const simulateTextInput = (Input) => {
212+
const rendered = ReactTestUtils.renderIntoDocument(<Input />);
213+
const input = ReactTestUtils.findRenderedDOMComponentWithTag(rendered, 'input');
214+
ReactTestUtils.Simulate.change(input, { target: { value: 'first' } });
215+
ReactTestUtils.Simulate.change(input, { target: { value: 'second' } });
216+
setTimeout(() => {
217+
ReactTestUtils.Simulate.change(input, { target: { value: 'third' } });
218+
}, 400);
219+
};
220+
221+
// eslint-disable-next-line
222+
class LockedInput extends React.Component {
223+
constructor(...params) {
224+
super(...params);
225+
this.onChange = this.onChange.bind(this);
226+
this.counter = 0;
227+
}
228+
229+
@lock
230+
onChange(e) {
231+
expect(e.target.value).toEqual('first');
232+
this.counter += 1;
233+
if (this.counter > 0) {
234+
expect(this.counter).toEqual(1);
235+
done();
236+
}
237+
}
238+
239+
render() {
240+
return (
241+
<input
242+
onChange={this.onChange}
243+
/>
244+
);
245+
}
246+
}
247+
248+
simulateTextInput(LockedInput);
249+
});
250+
209251
it('throttle', (done) => {
210252
const simulateTextInput = (Input) => {
211253
const rendered = ReactTestUtils.renderIntoDocument(<Input />);

0 commit comments

Comments
 (0)
Please sign in to comment.