Skip to content

Commit 6ce490a

Browse files
committed
feat: deep compare
1 parent 99673a8 commit 6ce490a

File tree

7 files changed

+80
-20
lines changed

7 files changed

+80
-20
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ class MyUser extends Fusion<any, any, MyStore> {
5252

5353
The third (optional) generic typing will help with your typings on `this.store`, meanwhile the first and the second arguments remain conventional(IProps, IState)
5454

55+
### Connecting with deep compare
56+
57+
There are situations where you would like to avoid unnesserary updates. For that preffix your key with `@`
58+
59+
```ts
60+
import { connect } from "fuse-react";
61+
@connect("@user")
62+
class MyUser extends Fusion<any, any, MyStore> {
63+
public render() {
64+
return (
65+
<div>{this.store.user.name}</div>
66+
);
67+
};
68+
}
69+
```
70+
71+
Once the dispatcher recieves an event and goes through all subscriptions it will check if the new value is different from the one in the store.
72+
5573
### Init
5674

5775
```tsx

fuse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ task("test", async context => {
1919
})
2020
task("dist", async context => {
2121
await context.clean();
22-
await context.prepareDistFolder();
2322
await exec("tsc")
2423
});
2524

2625
task("publish", async () => {
2726
await exec("dist")
27+
await context.prepareDistFolder();
2828
await npmPublish({path : "dist"});
2929
})
3030

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
{
22
"name": "fuse-react",
3-
"version": "1.0.2",
3+
"version": "1.0.0",
44
"main": "index.js",
55
"repository": "git@github.com:fuse-box/fuse-react.git",
66
"author": "nchanged <nchanged@gmail.com>",
77
"license": "MIT",
88
"dependencies": {
99
"@types/react": "^16.3.17",
10+
"deep-equal": "^1.0.1",
1011
"react": "*",
1112
"react-dom": "*"
1213
},
1314
"devDependencies": {
1415
"fuse-box": "^3.3.0-next.9",
1516
"typescript": "^2.9.1"
1617
}
17-
}
18+
}

src/Fusion.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,34 @@
11
import * as React from "react";
22
import { getStore, getSubscriptions } from './Store';
3-
3+
import * as equal from "deep-equal";
44
const Subscriptions = getSubscriptions();
55

66
export class Fusion<IProps, IState, IStore = null> extends React.Component<IProps, IState> {
77
public state: IState = {} as IState;
88
public props: IProps;
9-
public store : IStore = getStore();
9+
public store: IStore = getStore();
1010

1111
public _hasSubscriptions(obj: any) {
1212
const subscriptions = this.getConnectedStoreKeys();
1313
const store = getStore();
14-
if (Array.isArray(subscriptions)) {
14+
if (subscriptions) {
1515
for (const key in obj) {
16-
if (subscriptions.indexOf(key) > -1) {
17-
return true;
16+
const hasSubscription = subscriptions[key];
17+
if (hasSubscription) {
18+
if (!hasSubscription.deep) {
19+
return true;
20+
}
21+
if (hasSubscription.deep && !equal(store[key], obj[key])) {
22+
return true;
23+
}
1824
}
1925
}
2026
}
2127
return false;
2228
}
29+
2330
private getConnectedStoreKeys(): Array<string> {
24-
return this.constructor['$_connected_store_props'] || [];
31+
return this.constructor['$_connected_store_props'] || {};
2532
}
2633

2734
public _initialize() {
@@ -34,15 +41,17 @@ export class Fusion<IProps, IState, IStore = null> extends React.Component<IProp
3441

3542
componentWillMount() {
3643
const keys = this.getConnectedStoreKeys();
37-
if ( keys.length){
44+
if (Object.keys(keys).length) {
3845
Subscriptions.push(this);
3946
}
4047
this._initialize();
4148
}
4249

4350
componentWillUnmount() {
4451
const index = Subscriptions.indexOf(this);
45-
Subscriptions.splice(index, 1);
52+
if (index > -1) {
53+
Subscriptions.splice(index, 1);
54+
}
4655
}
4756

4857
componentWillReceiveProps(newProps) {

src/Store.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class StoreWrapper {
3232
}
3333
}
3434
}
35-
export function createStore(myClassContext: new () => any) : StoreWrapper {
35+
export function createStore(myClassContext: new () => any): StoreWrapper {
3636
Context = new myClassContext();
3737
if (typeof Context["init"] === "function") {
3838
Context["init"]();
@@ -51,24 +51,28 @@ export function getSubscriptions(): Array<any> {
5151
export function dispatch<Context>(obj: { [key: string]: any } | string, value?: (cnt: Context) => any) {
5252
const Subscriptions = storage.__Subscriptions;
5353
const store = getStore();
54-
let updates = obj;
54+
55+
let updates: any = obj;
5556
if (typeof obj === "object") {
5657
for (const key in obj) {
5758
if (typeof obj[key] === "function") {
58-
store[key] = obj[key](store);
59+
updates[key] = obj[key](store);
5960
} else {
60-
store[key] = obj[key]
61+
updates[key] = obj[key]
6162
}
6263
}
6364
}
6465
if (typeof obj === "string" && value) {
65-
store[obj] = value(store[obj]);
6666
updates = {};
67-
updates[obj] = store[obj];
67+
updates[obj] = value(store[obj]);
6868
}
6969
Wrapper.trigger(updates);
70+
7071
Subscriptions.forEach(component => {
7172
if (component._hasSubscriptions(updates)) {
73+
for (const key in updates) {
74+
store[key] = updates[key];
75+
}
7276
component._initialize();
7377
component.forceUpdate();
7478
}
@@ -79,7 +83,20 @@ export function dispatch<Context>(obj: { [key: string]: any } | string, value?:
7983
export function connect<TP, TC extends React.ComponentClass<TP>>(...args): any {
8084
return (Target: any) => {
8185
if (args.length) {
82-
Target["$_connected_store_props"] = args;
86+
const collection = {};
87+
for (const i in args) {
88+
89+
if (args.hasOwnProperty(i)) {
90+
let key = args[i];
91+
let deepEqual = false;
92+
if (key[0] === "@") {
93+
key = key.slice(1);
94+
deepEqual = true;
95+
}
96+
collection[key] = { deep: deepEqual };
97+
}
98+
}
99+
Target["$_connected_store_props"] = collection;
83100
}
84101
return Target;
85102
}

src/dev.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface IUser {
1010
age: number;
1111
}
1212
class MyStore {
13+
reset = {a : "b"}
1314
user = {
1415
name: "Bob",
1516
email: "bob@gmail.eomc",
@@ -22,11 +23,13 @@ wrapper.susbcribe("user", user => {
2223
})
2324

2425

25-
26-
class MyRootComponent extends Fusion<any, any> {
26+
@connect("@reset")
27+
class MyRootComponent extends Fusion<any, any, MyStore> {
2728
public render() {
29+
console.log("update");
2830
return (
2931
<div><input type="button" />
32+
{this.store.reset.a}
3033
<MyUser/>
3134
<Controls/>
3235
</div>
@@ -47,6 +50,12 @@ class Controls extends Fusion<any, any> {
4750
return user;
4851
});
4952
}
53+
private reset(){
54+
dispatch("reset", () => ({a : "b"}));
55+
}
56+
private reset2(){
57+
dispatch("reset", () => ({a : "a"}));
58+
}
5059
public render() {
5160
return (
5261
<div>
@@ -56,6 +65,8 @@ class Controls extends Fusion<any, any> {
5665
<input type="button" value="delete user" onClick={() => this.delete()}/>
5766
<input type="button" value="create user" onClick={() => this.create()}/>
5867
<input type="button" value="incrementAge11" onClick={() => this.incrementAge()}/>
68+
<input type="button" value="reset obj 1" onClick={() => this.reset()}/>
69+
<input type="button" value="reset obj 2" onClick={() => this.reset2()}/>
5970

6071
</div>
6172
</div>

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ decamelize@^1.1.1:
357357
version "1.2.0"
358358
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
359359

360+
deep-equal@^1.0.1:
361+
version "1.0.1"
362+
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
363+
360364
deep-extend@^0.6.0:
361365
version "0.6.0"
362366
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"

0 commit comments

Comments
 (0)