11// @flow
2- import React , { Component } from 'react' ;
2+ import React , { useRef } from 'react' ;
33import {
44 UnaryRelOp ,
55 Projection ,
@@ -18,7 +18,7 @@ import ReactDOM from 'react-dom';
1818
1919import './RelExpr.css' ;
2020
21- import type { Node } from 'react' ;
21+ import type { Node , StatelessFunctionalComponent } from 'react' ;
2222
2323type Props = {
2424 changeExpr : typeof changeExpr ,
@@ -27,18 +27,14 @@ type Props = {
2727} ;
2828
2929/** 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 ( ) ;
3632
3733 /**
3834 * @param expr - a relational algebra expression object to render
3935 * @return a component representing the top-most expression
4036 */
41- buildExpr ( expr : { [ string ] : any } ) : Node {
37+ const buildExpr = ( expr : { [ string ] : any } ) : Node => {
4238 // Don't try to render empty expressions
4339 if ( ! expr || Object . keys ( expr ) . length === 0 ) {
4440 return '' ;
@@ -55,8 +51,8 @@ class RelExpr extends Component<Props> {
5551 >
5652 < RelExpr
5753 expr = { expr . projection . children [ 0 ] }
58- changeExpr = { this . props . changeExpr }
59- ReactGA = { this . props . ReactGA }
54+ changeExpr = { props . changeExpr }
55+ ReactGA = { props . ReactGA }
6056 />
6157 </ UnaryRelOp >
6258 </ span >
@@ -74,8 +70,8 @@ class RelExpr extends Component<Props> {
7470 >
7571 < RelExpr
7672 expr = { expr . selection . children [ 0 ] }
77- changeExpr = { this . props . changeExpr }
78- ReactGA = { this . props . ReactGA }
73+ changeExpr = { props . changeExpr }
74+ ReactGA = { props . ReactGA }
7975 />
8076 </ UnaryRelOp >
8177 </ span >
@@ -89,8 +85,8 @@ class RelExpr extends Component<Props> {
8985 >
9086 < RelExpr
9187 expr = { expr . rename . children [ 0 ] }
92- changeExpr = { this . props . changeExpr }
93- ReactGA = { this . props . ReactGA }
88+ changeExpr = { props . changeExpr }
89+ ReactGA = { props . ReactGA }
9490 />
9591 </ UnaryRelOp >
9692 </ span >
@@ -115,15 +111,15 @@ class RelExpr extends Component<Props> {
115111 left = {
116112 < RelExpr
117113 expr = { expr [ type ] . left }
118- ReactGA = { this . props . ReactGA }
119- changeExpr = { this . props . changeExpr }
114+ ReactGA = { props . ReactGA }
115+ changeExpr = { props . changeExpr }
120116 />
121117 }
122118 right = {
123119 < RelExpr
124120 expr = { expr [ type ] . right }
125- ReactGA = { this . props . ReactGA }
126- changeExpr = { this . props . changeExpr }
121+ ReactGA = { props . ReactGA }
122+ changeExpr = { props . changeExpr }
127123 />
128124 }
129125 />
@@ -132,52 +128,51 @@ class RelExpr extends Component<Props> {
132128 default :
133129 throw new Error ( 'Invalid expression ' + JSON . stringify ( expr ) + '.' ) ;
134130 }
135- }
131+ } ;
136132
137133 /**
138134 * @param e - the event object which generated the click
139135 */
140- handleExprClick ( e : SyntheticMouseEvent < HTMLElement > ) : void {
136+ const handleExprClick = ( e : SyntheticMouseEvent < HTMLElement > ) : void => {
141137 e. stopPropagation ( ) ;
142138 const node =
143- ReactDOM . findDOMNode ( this ) instanceof HTMLElement
144- ? ReactDOM . findDOMNode ( this )
139+ ReactDOM . findDOMNode ( nodeRef . current ) instanceof HTMLElement
140+ ? ReactDOM . findDOMNode ( nodeRef . current )
145141 : undefined ;
146142
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 ) ;
149145 }
150146
151- this . props . ReactGA . event ( {
147+ props . ReactGA . event ( {
152148 category : 'User Selecting Relational Algebra Enclosure' ,
153- action : Object . keys ( this . props . expr ) [ 0 ] ,
149+ action : Object . keys ( props . expr ) [ 0 ] ,
154150 } ) ;
155- }
151+ } ;
156152
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 '' ;
180155 }
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+ } ;
182177
183178export default RelExpr ;
0 commit comments