Skip to content

Commit d4864f1

Browse files
author
Sheeshpaul Kamboj
committed
Wrapping existing connectedCallback and disconnectedCall
Wrapping existing connectedCallback and disconnectedCall for establishing state management.
1 parent 88fb0a6 commit d4864f1

7 files changed

+439
-199
lines changed

Diff for: package-lock.json

+366-140
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+10-10
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,29 @@
3535
},
3636
"dependencies": {},
3737
"devDependencies": {
38-
"@babel/core": "^7.8.4",
38+
"@babel/core": "^7.8.7",
3939
"@babel/plugin-proposal-class-properties": "^7.8.3",
4040
"@babel/plugin-proposal-object-rest-spread": "^7.8.3",
41-
"@babel/preset-env": "^7.8.4",
41+
"@babel/preset-env": "^7.8.7",
4242
"@babel/preset-typescript": "^7.8.3",
43-
"@types/jest": "^25.1.3",
44-
"@typescript-eslint/eslint-plugin": "^2.20.0",
45-
"@typescript-eslint/parser": "^2.20.0",
43+
"@types/jest": "^25.1.4",
44+
"@typescript-eslint/eslint-plugin": "^2.23.0",
45+
"@typescript-eslint/parser": "^2.23.0",
4646
"babel-jest": "^25.1.0",
4747
"eslint": "^6.8.0",
4848
"eslint-config-prettier": "^6.10.0",
4949
"eslint-plugin-prettier": "^3.1.2",
5050
"jest": "^25.1.0",
5151
"prettier": "^1.19.1",
52-
"rimraf": "^3.0.1",
53-
"rollup": "^1.30.1",
54-
"rollup-plugin-babel": "^4.3.3",
52+
"rimraf": "^3.0.2",
53+
"rollup": "^2.0.6",
54+
"rollup-plugin-babel": "^4.4.0",
5555
"rollup-plugin-commonjs": "^10.1.0",
5656
"rollup-plugin-node-resolve": "^5.2.0",
5757
"rollup-plugin-replace": "^2.2.0",
5858
"rollup-plugin-uglify-es": "0.0.1",
59-
"tslib": "^1.10.0",
60-
"typescript": "^3.8.2"
59+
"tslib": "^1.11.1",
60+
"typescript": "^3.8.3"
6161
},
6262
"npmName": "webcomponents-redux",
6363
"npmFileMap": [

Diff for: src/connect.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ export function connect(className: Function, mixinStore: object): void {
3131

3232
Object.assign(className.prototype, mixinWebcomponent);
3333

34-
if (!className.prototype.hasOwnProperty('connectedCallback')) {
35-
Object.assign(className.prototype, mixinConnectedCallback);
36-
}
34+
className.prototype.mixinExistingConnectedCallback = className.prototype.connectedCallback;
35+
Object.assign(className.prototype, mixinConnectedCallback);
3736

38-
if (!className.prototype.hasOwnProperty('disconnectedCallback')) {
39-
Object.assign(className.prototype, mixinDisconnectedCallback);
40-
}
37+
className.prototype.mixinExistingDisconnectedCallback = className.prototype.disconnectedCallback;
38+
Object.assign(className.prototype, mixinDisconnectedCallback);
4139

4240
className.prototype.mixinStore = mixinStore;
4341
}

Diff for: src/mixin-connectedcallback.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ interface MixinConnectedCallback {
66
}
77

88
/**
9-
* The mixin for generic connectedCallback implementation.
9+
* The mixin for connectedCallback implementation.
1010
*/
1111
export const mixinConnectedCallback: MixinConnectedCallback = {
1212
/**
13-
* Generic implementation for Web Component connectedCallback lifecycle event.
14-
* Calls the super and connects to Redux store.
13+
* Calls the existing connectedCallback lifecycle event when present, and connects to Redux store.
1514
*/
1615
connectedCallback() {
17-
// Issue is super is not present here
18-
// Walking the prototype chain to call the connectedCallback on parent (super)
19-
2016
// @ts-ignore
21-
this.__proto__.__proto__.connectedCallback.call(this);
17+
this.mixinExistingConnectedCallback && this.mixinExistingConnectedCallback();
2218

2319
// @ts-ignore
24-
this.connectState();
20+
this.mixinConnectState();
2521
},
2622
};

Diff for: src/mixin-disconnectedcallback.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ interface MixinDisconnectedCallback {
66
}
77

88
/**
9-
* The mixin for generic disconnectedCallback implementation.
9+
* The mixin for disconnectedCallback implementation.
1010
*/
1111
export const mixinDisconnectedCallback: MixinDisconnectedCallback = {
1212
/**
13-
* Generic implementation for Web Component disconnectedCallback lifecycle event.
14-
* Calls the super and disconnect with Redux store.
13+
* Calls the existing disconnectedCallback lifecycle event, and disconnect with Redux store.
1514
*/
1615
disconnectedCallback() {
17-
// Issue is super is not present here
18-
// Walking the prototype chain to call the connectedCallback on parent (super)
16+
// @ts-ignore
17+
this.mixinExistingDisconnectedCallback && this.mixinExistingDisconnectedCallback();
1918

2019
//@ts-ignore
21-
this.__proto__.__proto__.disconnectedCallback.call(this);
22-
23-
//@ts-ignore
24-
this.disconnectState();
20+
this.mixinDisconnectState();
2521
},
2622
};

Diff for: src/mixin-webcomponent.ts

+20-8
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ interface MixinWebComponent {
1414
mixinStore: null | Store;
1515
mixinState: undefined | object;
1616
mixinUnsubscribeStore: null | Function;
17-
connectState: Function;
18-
disconnectState: Function;
19-
onMixinStateChange: Function;
17+
mixinExistingConnectedCallback: null | Function;
18+
mixinExistingDisconnectedCallback: null | Function;
19+
mixinConnectState: Function;
20+
mixinDisconnectState: Function;
21+
mixinOnStateChange: Function;
2022
mapDispatchToProps?: Function;
2123
mapStateToProps?: Function;
2224
}
@@ -40,10 +42,20 @@ export const mixinWebcomponent: MixinWebComponent = {
4042
*/
4143
mixinUnsubscribeStore: null,
4244

45+
/**
46+
* The existing connectedCallback function.
47+
*/
48+
mixinExistingConnectedCallback: null,
49+
50+
/**
51+
* The existing disconnectedCallback function.
52+
*/
53+
mixinExistingDisconnectedCallback: null,
54+
4355
/**
4456
* Sets up state change and dispatch functionality.
4557
*/
46-
connectState() {
58+
mixinConnectState() {
4759
// Step 1: To the instance add dispatch functions as properties
4860
if (this.mapDispatchToProps) {
4961
const obj = this.mapDispatchToProps(this.mixinStore!.dispatch);
@@ -64,15 +76,15 @@ export const mixinWebcomponent: MixinWebComponent = {
6476
// Step 3: Save the current state and subscribe to store change event
6577
this.mixinState = nextState;
6678

67-
this.onMixinStateChange = this.onMixinStateChange.bind(this);
79+
this.mixinOnStateChange = this.mixinOnStateChange.bind(this);
6880

69-
this.mixinUnsubscribeStore = this.mixinStore!.subscribe(this.onMixinStateChange);
81+
this.mixinUnsubscribeStore = this.mixinStore!.subscribe(this.mixinOnStateChange);
7082
},
7183

7284
/**
7385
* Unsubscribe from store change events.
7486
*/
75-
disconnectState() {
87+
mixinDisconnectState() {
7688
if (this.mixinUnsubscribeStore) {
7789
this.mixinUnsubscribeStore();
7890
this.mixinUnsubscribeStore = null;
@@ -82,7 +94,7 @@ export const mixinWebcomponent: MixinWebComponent = {
8294
/**
8395
* Upon state change, call mapStateToProps, only when next state is different than current state.
8496
*/
85-
onMixinStateChange() {
97+
mixinOnStateChange() {
8698
const nextState = this.mixinStore!.getState();
8799

88100
if (nextState === this.mixinState) {

Diff for: test/connect.spec.ts

+30-18
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,20 @@ describe('connect', () => {
99
connect(Component, {});
1010

1111
// Verify
12-
const hasConnectState = Component.prototype.hasOwnProperty('connectState');
13-
const hasDisconnectState = Component.prototype.hasOwnProperty('disconnectState');
14-
const hasOnMixinStateChange = Component.prototype.hasOwnProperty('onMixinStateChange');
12+
const hasMixinConnectState = Component.prototype.hasOwnProperty('mixinConnectState');
13+
const hasMixinDisconnectState = Component.prototype.hasOwnProperty('mixinDisconnectState');
14+
const hasMixinOnStateChange = Component.prototype.hasOwnProperty('mixinOnStateChange');
15+
const hasConnectedCallback = Component.prototype.hasOwnProperty('connectedCallback');
16+
const hasDisconnectedCallback = Component.prototype.hasOwnProperty('disconnectedCallback');
1517

16-
expect(hasConnectState).toBe(true);
17-
expect(hasDisconnectState).toBe(true);
18-
expect(hasOnMixinStateChange).toBe(true);
18+
expect(hasMixinConnectState).toBe(true);
19+
expect(hasMixinDisconnectState).toBe(true);
20+
expect(hasMixinOnStateChange).toBe(true);
21+
expect(hasConnectedCallback).toBe(true);
22+
expect(hasDisconnectedCallback).toBe(true);
1923
});
2024

21-
it('should add connectedCallback', () => {
25+
it('should add connectedCallback, when there is no existing connectedCallback', () => {
2226
// Setup
2327
class Component {}
2428

@@ -27,30 +31,34 @@ describe('connect', () => {
2731

2832
// Verify
2933
const hasConnectedCallback = Component.prototype.hasOwnProperty('connectedCallback');
30-
3134
expect(hasConnectedCallback).toBe(true);
35+
36+
// @ts-ignore
37+
expect(Component.prototype.mixinExistingConnectedCallback).toBe(undefined);
3238
});
3339

34-
it('should not add connectedCallback', () => {
40+
it('should add connectedCallback keeping the existing connectedCallback', () => {
3541
// Setup
3642
class Component {
3743
connectedCallback(): void {
3844
// The empty implementation
3945
}
4046
}
4147

42-
const before = Component.prototype.connectedCallback;
48+
const existingConnectedCallback = Component.prototype.connectedCallback;
4349

4450
// Act
4551
connect(Component, {});
4652

4753
// Verify
48-
const after = Component.prototype.connectedCallback;
54+
const hasConnectedCallback = Component.prototype.hasOwnProperty('connectedCallback');
55+
expect(hasConnectedCallback).toBe(true);
4956

50-
expect(after).toBe(before);
57+
// @ts-ignore
58+
expect(Component.prototype.mixinExistingConnectedCallback).toBe(existingConnectedCallback);
5159
});
5260

53-
it('should add disconnectedCallback', () => {
61+
it('should add disconnectedCallback, when there is no existing disconnectedCallback', () => {
5462
// Setup
5563
class Component {}
5664

@@ -59,26 +67,30 @@ describe('connect', () => {
5967

6068
// Verify
6169
const hasDisconnectedCallback = Component.prototype.hasOwnProperty('disconnectedCallback');
62-
6370
expect(hasDisconnectedCallback).toBe(true);
71+
72+
// @ts-ignore
73+
expect(Component.prototype.mixinExistingDisconnectedCallback).toBe(undefined);
6474
});
6575

66-
it('should not add disconnectedCallback', () => {
76+
it('should add disconnectedCallback keeping the exsiting disconnectedCallback', () => {
6777
// Setup
6878
class Component {
6979
disconnectedCallback(): void {
7080
// The empty implementation
7181
}
7282
}
7383

74-
const before = Component.prototype.disconnectedCallback;
84+
const existingDisconnectedCallback = Component.prototype.disconnectedCallback;
7585

7686
// Act
7787
connect(Component, {});
7888

7989
// Verify
80-
const after = Component.prototype.disconnectedCallback;
90+
const hasDisconnectedCallback = Component.prototype.hasOwnProperty('disconnectedCallback');
91+
expect(hasDisconnectedCallback).toBe(true);
8192

82-
expect(after).toBe(before);
93+
// @ts-ignore
94+
expect(Component.prototype.mixinExistingDisconnectedCallback).toBe(existingDisconnectedCallback)
8395
});
8496
});

0 commit comments

Comments
 (0)