@@ -29,15 +29,20 @@ export class SignatureCanvas extends Component<SignatureCanvasProps> {
29
29
clearOnResize : true
30
30
}
31
31
32
- // this is some hack-ish init and casting to avoid `| null` everywhere :/
33
- /* eslint-disable @typescript-eslint/consistent-type-assertions */
34
- _sigPad : SignaturePad = { } as SignaturePad
35
- _canvas : HTMLCanvasElement = { } as HTMLCanvasElement
36
- /* eslint-enable @typescript-eslint/consistent-type-assertions */
32
+ static refNullError = new Error ( 'react-signature-canvas is currently ' +
33
+ 'mounting or unmounting: React refs are null during this phase.' )
34
+
35
+ // shortcut reference (https://stackoverflow.com/a/29244254/3431180)
36
+ private readonly staticThis = this . constructor as typeof SignatureCanvas
37
+
38
+ _sigPad : SignaturePad | null = null
39
+ _canvas : HTMLCanvasElement | null = null
37
40
38
41
private readonly setRef = ( ref : HTMLCanvasElement | null ) : void => {
39
- if ( ref !== null ) {
40
- this . _canvas = ref
42
+ this . _canvas = ref
43
+ // if component is unmounted, set internal references to null
44
+ if ( this . _canvas === null ) {
45
+ this . _sigPad = null
41
46
}
42
47
}
43
48
@@ -47,7 +52,8 @@ export class SignatureCanvas extends Component<SignatureCanvasProps> {
47
52
}
48
53
49
54
componentDidMount : Component [ 'componentDidMount' ] = ( ) => {
50
- this . _sigPad = new SignaturePad ( this . _canvas , this . _excludeOurProps ( ) )
55
+ const canvas = this . getCanvas ( )
56
+ this . _sigPad = new SignaturePad ( canvas , this . _excludeOurProps ( ) )
51
57
this . _resizeCanvas ( )
52
58
this . on ( )
53
59
}
@@ -63,23 +69,30 @@ export class SignatureCanvas extends Component<SignatureCanvasProps> {
63
69
64
70
// return the canvas ref for operations like toDataURL
65
71
getCanvas = ( ) : HTMLCanvasElement => {
72
+ if ( this . _canvas === null ) {
73
+ throw this . staticThis . refNullError
74
+ }
66
75
return this . _canvas
67
76
}
68
77
69
78
// return a trimmed copy of the canvas
70
79
getTrimmedCanvas = ( ) : HTMLCanvasElement => {
71
80
// copy the canvas
81
+ const canvas = this . getCanvas ( )
72
82
const copy = document . createElement ( 'canvas' )
73
- copy . width = this . _canvas . width
74
- copy . height = this . _canvas . height
83
+ copy . width = canvas . width
84
+ copy . height = canvas . height
75
85
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
76
- copy . getContext ( '2d' ) ! . drawImage ( this . _canvas , 0 , 0 )
86
+ copy . getContext ( '2d' ) ! . drawImage ( canvas , 0 , 0 )
77
87
// then trim it
78
88
return trimCanvas ( copy )
79
89
}
80
90
81
91
// return the internal SignaturePad reference
82
92
getSignaturePad = ( ) : SignaturePad => {
93
+ if ( this . _sigPad === null ) {
94
+ throw this . staticThis . refNullError
95
+ }
83
96
return this . _sigPad
84
97
}
85
98
@@ -98,7 +111,7 @@ export class SignatureCanvas extends Component<SignatureCanvasProps> {
98
111
return
99
112
}
100
113
101
- const canvas = this . _canvas
114
+ const canvas = this . getCanvas ( )
102
115
/* When zoomed out to less than 100%, for some very strange reason,
103
116
some browsers report devicePixelRatio as less than 1
104
117
and only part of the canvas is cleared then. */
@@ -124,36 +137,36 @@ export class SignatureCanvas extends Component<SignatureCanvasProps> {
124
137
//
125
138
on : SignaturePad [ 'on' ] = ( ) => {
126
139
window . addEventListener ( 'resize' , this . _checkClearOnResize )
127
- return this . _sigPad . on ( )
140
+ return this . getSignaturePad ( ) . on ( )
128
141
}
129
142
130
143
off : SignaturePad [ 'off' ] = ( ) => {
131
144
window . removeEventListener ( 'resize' , this . _checkClearOnResize )
132
- return this . _sigPad . off ( )
145
+ return this . getSignaturePad ( ) . off ( )
133
146
}
134
147
135
148
clear : SignaturePad [ 'clear' ] = ( ) => {
136
- return this . _sigPad . clear ( )
149
+ return this . getSignaturePad ( ) . clear ( )
137
150
}
138
151
139
152
isEmpty : SignaturePad [ 'isEmpty' ] = ( ) => {
140
- return this . _sigPad . isEmpty ( )
153
+ return this . getSignaturePad ( ) . isEmpty ( )
141
154
}
142
155
143
156
fromDataURL : SignaturePad [ 'fromDataURL' ] = ( dataURL , options ) => {
144
- return this . _sigPad . fromDataURL ( dataURL , options )
157
+ return this . getSignaturePad ( ) . fromDataURL ( dataURL , options )
145
158
}
146
159
147
160
toDataURL : SignaturePad [ 'toDataURL' ] = ( type , encoderOptions ) => {
148
- return this . _sigPad . toDataURL ( type , encoderOptions )
161
+ return this . getSignaturePad ( ) . toDataURL ( type , encoderOptions )
149
162
}
150
163
151
164
fromData : SignaturePad [ 'fromData' ] = ( pointGroups ) => {
152
- return this . _sigPad . fromData ( pointGroups )
165
+ return this . getSignaturePad ( ) . fromData ( pointGroups )
153
166
}
154
167
155
168
toData : SignaturePad [ 'toData' ] = ( ) => {
156
- return this . _sigPad . toData ( )
169
+ return this . getSignaturePad ( ) . toData ( )
157
170
}
158
171
}
159
172
0 commit comments