Skip to content

Commit

Permalink
feat: implement shouldUpdate() and pure()
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Feb 16, 2018
1 parent b647edc commit c54d8b7
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 4 deletions.
3 changes: 2 additions & 1 deletion docs/en/Inversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ This effectively allows you to have

in JSX tree without having to write stateful React components.

- [`invert()`](./invert.md) and [`<Inverted>`](./invert.md#inverted) &mdash; inverts DOM element `ref`.
- [`<State>`](./State.md) &mdash; inverts `.state` and `.setState()` method.
- [`<Toggle>`](./Toggle.md), [`<Flipflop>`](./Flipflop.md), [`<Value>`](./Value.md), [`<Counter>`](./Counter.md), [`<List>`](./List.md), and [`<Map>`](./Map.md)
- [`<ShouldUpdate>`](./ShouldUpdate.md) &mdash; inverts `.shouldComponentUpdate()` life-cycle method.
- [`invert()`](./invert.md) and [`<Inverted>`](./invert.md#inverted) &mdash; inverts DOM element `ref` reference.


## Example
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"freestyler-context": "^1.3.3",
"freestyler-renderer": "^1.3.2",
"screenfull": "^3.3.2",
"fast-extend": "0.0.2"
"fast-extend": "1.0.2",
"fast-shallow-equal": "0.1.1"
},
"peerDependencies": {
"react": "*",
Expand Down
2 changes: 1 addition & 1 deletion src/ShouldUpdate/__story__/Example1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export class Example1 extends Component {
</ShouldUpdate>
);
}
}
}
19 changes: 19 additions & 0 deletions src/ShouldUpdate/__story__/Example2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Component, createElement as h} from 'react';
import {shouldUpdate} from '..';

const Print = ({cnt}) => <span>Click me ({cnt})</span>;
const LazyPrint = shouldUpdate((props) => props.cnt > 3)(Print);

export class Example2 extends Component {
state = {
cnt: 0
};

render () {
return (
<div onClick={() => this.setState({cnt: this.state.cnt + 1})}>
<LazyPrint cnt={this.state.cnt} />
</div>
);
}
}
19 changes: 19 additions & 0 deletions src/ShouldUpdate/__story__/Example3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Component, createElement as h} from 'react';
import {shouldUpdate} from '..';

const Print = ({cnt}) => <span>Click me ({cnt})</span>;
const LazyPrint = shouldUpdate((props) => !(props.cnt % 3))(Print);

export class Example3 extends Component {
state = {
cnt: 0
};

render () {
return (
<div onClick={() => this.setState({cnt: this.state.cnt + 1})}>
<LazyPrint cnt={this.state.cnt} />
</div>
);
}
}
23 changes: 23 additions & 0 deletions src/ShouldUpdate/__story__/Example4.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Component, createElement as h} from 'react';
import {pure} from '../../pure';

const Print = ({cnt}) => {
console.log('RENDERING');

return <span>Click me ({cnt})</span>;
};
const LazyPrint = pure(Print);

export class Example4 extends Component {
state = {
cnt: 0
};

render () {
return (
<div onClick={() => this.setState({cnt: this.state.cnt + 1})}>
<LazyPrint cnt={Math.floor(this.state.cnt / 3) * 3} />
</div>
);
}
}
15 changes: 14 additions & 1 deletion src/ShouldUpdate/__story__/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import {Component, createElement as h} from 'react';
import {storiesOf} from '@storybook/react';
import {action} from '@storybook/addon-actions';
import {linkTo} from '@storybook/addon-links';
import {ShouldUpdate} from '..';
import {ShouldUpdate, shouldUpdate} from '..';
import ShowDocs from '../../../.storybook/ShowDocs'
import {Example1} from './Example1';
import {Example2} from './Example2';
import {Example3} from './Example3';
import {Example4} from './Example4';

storiesOf('Inversion/ShouldUpdate', module)
// .add('Documentation', () => h(ShowDocs, {md: require('../../../docs/en/ShouldUpdate.md')}))
Expand All @@ -14,3 +17,13 @@ storiesOf('Inversion/ShouldUpdate', module)
)
)
.add('When greater than 3', () => <Example1 />)
.add('Passes props', () => (
<ShouldUpdate when={() => true} props={{foo: 'bar'}}>{({foo}) =>
<div>
{foo}
</div>
}</ShouldUpdate>
))
.add('HOC - greater than 3', () => <Example2 />)
.add('HOC - increments of 3', () => <Example3 />)
.add('pure()', () => <Example4 />)
4 changes: 4 additions & 0 deletions src/ShouldUpdate/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Component} from 'react';
import {h} from '../util';
import renderProp from '../util/renderProp';

export interface IShouldUpdateProps {
Expand All @@ -18,3 +19,6 @@ export class ShouldUpdate extends Component<IShouldUpdateProps, IShouldUpdateSta
return renderProp(this.props, this.props.props);
}
}

export const shouldUpdate = (when) => (Comp) => (props) =>
h(ShouldUpdate, {when, props}, h(Comp, props));
4 changes: 4 additions & 0 deletions src/pure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {equal} from 'fast-shallow-equal';
import {shouldUpdate} from './ShouldUpdate';

export const pure = shouldUpdate((a, b) => !equal(a, b));
21 changes: 21 additions & 0 deletions src/util/shallowEqual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const keyList = Object.keys;
const hasProp = Object.prototype.hasOwnProperty;

const shallowEqual: (a, b) => boolean = (a, b) => {
if (a === b) return true;
if (!a || !b) return false;
if (!(a instanceof Object) || !(b instanceof Object)) return false;

const keys = keyList(a);
const length = keys.length;

for (let i = 0; i < length; i++)
if (!(keys[i] in b)) return false;

for (let i = 0; i < length; i++)
if (a[keys[i]] !== b[keys[i]]) return false;

return length === keyList(b).length;
}

export default

0 comments on commit c54d8b7

Please sign in to comment.