1
1
// @flow
2
- import React , { Component } from 'react' ;
2
+ import React , { useRef } from 'react' ;
3
3
import {
4
4
UnaryRelOp ,
5
5
Projection ,
@@ -18,7 +18,7 @@ import ReactDOM from 'react-dom';
18
18
19
19
import './RelExpr.css' ;
20
20
21
- import type { Node } from 'react' ;
21
+ import type { Node , StatelessFunctionalComponent } from 'react' ;
22
22
23
23
type Props = {
24
24
changeExpr : typeof changeExpr ,
@@ -27,18 +27,14 @@ type Props = {
27
27
} ;
28
28
29
29
/** A graphical representation of a relational algebra expression */
30
- class RelExpr extends Component < Props > {
31
- constructor ( ) {
32
- super ( ) ;
33
- // $FlowFixMe[method-unbinding]
34
- ( this : any ) . handleExprClick = this . handleExprClick . bind ( this ) ;
35
- }
30
+ const RelExpr : StatelessFunctionalComponent < Props > = (props) => {
31
+ const nodeRef = useRef ( ) ;
36
32
37
33
/**
38
34
* @param expr - a relational algebra expression object to render
39
35
* @return a component representing the top-most expression
40
36
*/
41
- buildExpr ( expr : { [ string ] : any } ) : Node {
37
+ const buildExpr = ( expr : { [ string ] : any } ) : Node => {
42
38
// Don't try to render empty expressions
43
39
if ( ! expr || Object . keys ( expr ) . length === 0 ) {
44
40
return '' ;
@@ -55,8 +51,8 @@ class RelExpr extends Component<Props> {
55
51
>
56
52
< RelExpr
57
53
expr = { expr . projection . children [ 0 ] }
58
- changeExpr = { this . props . changeExpr }
59
- ReactGA = { this . props . ReactGA }
54
+ changeExpr = { props . changeExpr }
55
+ ReactGA = { props . ReactGA }
60
56
/>
61
57
</ UnaryRelOp >
62
58
</ span >
@@ -74,8 +70,8 @@ class RelExpr extends Component<Props> {
74
70
>
75
71
< RelExpr
76
72
expr = { expr . selection . children [ 0 ] }
77
- changeExpr = { this . props . changeExpr }
78
- ReactGA = { this . props . ReactGA }
73
+ changeExpr = { props . changeExpr }
74
+ ReactGA = { props . ReactGA }
79
75
/>
80
76
</ UnaryRelOp >
81
77
</ span >
@@ -89,8 +85,8 @@ class RelExpr extends Component<Props> {
89
85
>
90
86
< RelExpr
91
87
expr = { expr . rename . children [ 0 ] }
92
- changeExpr = { this . props . changeExpr }
93
- ReactGA = { this . props . ReactGA }
88
+ changeExpr = { props . changeExpr }
89
+ ReactGA = { props . ReactGA }
94
90
/>
95
91
</ UnaryRelOp >
96
92
</ span >
@@ -115,15 +111,15 @@ class RelExpr extends Component<Props> {
115
111
left = {
116
112
< RelExpr
117
113
expr = { expr [ type ] . left }
118
- ReactGA = { this . props . ReactGA }
119
- changeExpr = { this . props . changeExpr }
114
+ ReactGA = { props . ReactGA }
115
+ changeExpr = { props . changeExpr }
120
116
/>
121
117
}
122
118
right = {
123
119
< RelExpr
124
120
expr = { expr [ type ] . right }
125
- ReactGA = { this . props . ReactGA }
126
- changeExpr = { this . props . changeExpr }
121
+ ReactGA = { props . ReactGA }
122
+ changeExpr = { props . changeExpr }
127
123
/>
128
124
}
129
125
/>
@@ -132,52 +128,51 @@ class RelExpr extends Component<Props> {
132
128
default :
133
129
throw new Error ( 'Invalid expression ' + JSON . stringify ( expr ) + '.' ) ;
134
130
}
135
- }
131
+ } ;
136
132
137
133
/**
138
134
* @param e - the event object which generated the click
139
135
*/
140
- handleExprClick ( e : SyntheticMouseEvent < HTMLElement > ) : void {
136
+ const handleExprClick = ( e : SyntheticMouseEvent < HTMLElement > ) : void => {
141
137
e. stopPropagation ( ) ;
142
138
const node =
143
- ReactDOM . findDOMNode ( this ) instanceof HTMLElement
144
- ? ReactDOM . findDOMNode ( this )
139
+ ReactDOM . findDOMNode ( nodeRef . current ) instanceof HTMLElement
140
+ ? ReactDOM . findDOMNode ( nodeRef . current )
145
141
: undefined ;
146
142
147
- if ( node instanceof HTMLElement && this . props . changeExpr ) {
148
- this . props . changeExpr ( this . props . expr , node ) ;
143
+ if ( node instanceof HTMLElement && props . changeExpr ) {
144
+ props . changeExpr ( props . expr , node ) ;
149
145
}
150
146
151
- this . props . ReactGA . event ( {
147
+ props . ReactGA . event ( {
152
148
category : 'User Selecting Relational Algebra Enclosure' ,
153
- action : Object . keys ( this . props . expr ) [ 0 ] ,
149
+ action : Object . keys ( props . expr ) [ 0 ] ,
154
150
} ) ;
155
- }
151
+ } ;
156
152
157
- render ( ) : Node {
158
- if ( ! this . props . expr || Object . keys ( this . props . expr ) . length === 0 ) {
159
- return '' ;
160
- }
161
- const type = Object . keys ( this . props . expr ) [ 0 ] ;
162
- if ( type === 'relation' ) {
163
- return (
164
- < span className = "RelExpr" style = { { margin : '.4em' } } >
165
- { this . buildExpr ( this . props . expr ) }
166
- </ span >
167
- ) ;
168
- } else {
169
- return (
170
- < span
171
- className = "RelExpr"
172
- // $FlowFixMe[method-unbinding]
173
- onClick = { this . handleExprClick }
174
- style = { { margin : '.4em' } }
175
- >
176
- { this . buildExpr ( this . props . expr ) }
177
- </ span >
178
- ) ;
179
- }
153
+ if ( ! props . expr || Object . keys ( props . expr ) . length === 0 ) {
154
+ return '' ;
180
155
}
181
- }
156
+ const type = Object . keys ( props . expr ) [ 0 ] ;
157
+ if ( type === 'relation' ) {
158
+ return (
159
+ < span className = "RelExpr" style = { { margin : '.4em' } } >
160
+ { buildExpr ( props . expr ) }
161
+ </ span >
162
+ ) ;
163
+ } else {
164
+ return (
165
+ < span
166
+ className = "RelExpr"
167
+ // $FlowFixMe[method-unbinding]
168
+ onClick = { handleExprClick }
169
+ style = { { margin : '.4em' } }
170
+ ref = { nodeRef }
171
+ >
172
+ { buildExpr ( props . expr ) }
173
+ </ span >
174
+ ) ;
175
+ }
176
+ } ;
182
177
183
178
export default RelExpr ;
0 commit comments