diff --git a/.eslintrc.json b/.eslintrc.json index a1d707ab..3b033c4f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -20,6 +20,7 @@ "no-var": 2, "react/jsx-indent": [2, 2], "react/jsx-indent-props": [2, 2], + "react/no-find-dom-node": 2, "react/no-set-state": 1, "react/require-optimization": 0 } diff --git a/src/browser/components/LoginModal.jsx b/src/browser/components/LoginModal.jsx index 87db828e..3a251fdb 100644 --- a/src/browser/components/LoginModal.jsx +++ b/src/browser/components/LoginModal.jsx @@ -3,19 +3,20 @@ // See LICENSE.txt for license information. import React from 'react'; import PropTypes from 'prop-types'; -import {findDOMNode} from 'react-dom'; import {Button, Col, ControlLabel, Form, FormGroup, FormControl, Modal} from 'react-bootstrap'; export default class LoginModal extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); + this.usernameRef = React.createRef(); + this.passwordRef = React.createRef(); } handleSubmit(event) { event.preventDefault(); - const usernameNode = findDOMNode(this.refs.username); - const passwordNode = findDOMNode(this.refs.password); + const usernameNode = this.usernameRef.current; + const passwordNode = this.passwordRef.current; this.props.onLogin(this.props.request, usernameNode.value, passwordNode.value); usernameNode.value = ''; passwordNode.value = ''; @@ -53,7 +54,7 @@ export default class LoginModal extends React.Component { { e.stopPropagation(); }} @@ -69,7 +70,7 @@ export default class LoginModal extends React.Component { { e.stopPropagation(); }} diff --git a/src/browser/components/MattermostView.jsx b/src/browser/components/MattermostView.jsx index 03c0e27c..424c4507 100644 --- a/src/browser/components/MattermostView.jsx +++ b/src/browser/components/MattermostView.jsx @@ -9,7 +9,6 @@ import url from 'url'; import React from 'react'; import PropTypes from 'prop-types'; -import {findDOMNode} from 'react-dom'; import {ipcRenderer, remote, shell} from 'electron'; import contextMenu from '../js/contextMenu'; @@ -63,6 +62,8 @@ export default class MattermostView extends React.Component { this.goForward = this.goForward.bind(this); this.getSrc = this.getSrc.bind(this); this.handleDeepLink = this.handleDeepLink.bind(this); + + this.webviewRef = React.createRef(); } handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned) { @@ -73,7 +74,7 @@ export default class MattermostView extends React.Component { componentDidMount() { const self = this; - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; webview.addEventListener('did-fail-load', (e) => { console.log(self.props.name, 'webview did-fail-load', e); @@ -218,7 +219,7 @@ export default class MattermostView extends React.Component { reloadTimeoutID: null, isLoaded: false, }); - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; webview.reload(); } @@ -226,14 +227,14 @@ export default class MattermostView extends React.Component { this.setState({ errorInfo: null, }); - const webContents = findDOMNode(this.refs.webview).getWebContents(); + const webContents = this.webviewRef.current.getWebContents(); webContents.session.clearCache(() => { webContents.reload(); }); } focusOnWebView() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; const webContents = webview.getWebContents(); // webContents might not be created yet. if (webContents && !webContents.isFocused()) { webview.focus(); @@ -242,32 +243,32 @@ export default class MattermostView extends React.Component { } canGoBack() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; return webview.getWebContents().canGoBack(); } canGoForward() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; return webview.getWebContents().canGoForward(); } goBack() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; webview.getWebContents().goBack(); } goForward() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; webview.getWebContents().goForward(); } getSrc() { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; return webview.src; } handleDeepLink(relativeUrl) { - const webview = findDOMNode(this.refs.webview); + const webview = this.webviewRef.current; webview.executeJavaScript( 'history.pushState(null, null, "' + relativeUrl + '");' ); @@ -314,7 +315,7 @@ export default class MattermostView extends React.Component { id={this.props.id} preload={preloadJS} src={this.props.src} - ref='webview' + ref={this.webviewRef} /> { loadingImage } ); diff --git a/src/browser/components/SettingsPage.jsx b/src/browser/components/SettingsPage.jsx index ba2c75eb..94036b60 100644 --- a/src/browser/components/SettingsPage.jsx +++ b/src/browser/components/SettingsPage.jsx @@ -6,7 +6,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; import {Button, Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row} from 'react-bootstrap'; import {ipcRenderer, remote} from 'electron'; @@ -74,6 +73,8 @@ export default class SettingsPage extends React.Component { this.handleChangeEnableHardwareAcceleration = this.handleChangeEnableHardwareAcceleration.bind(this); this.updateTeam = this.updateTeam.bind(this); this.addServer = this.addServer.bind(this); + + this.trayIconThemeRef = React.createRef(); } componentDidMount() { @@ -214,7 +215,7 @@ export default class SettingsPage extends React.Component { handleChangeTrayIconTheme() { this.setState({ - trayIconTheme: ReactDOM.findDOMNode(this.refs.trayIconTheme).value, + trayIconTheme: this.trayIconThemeRef.current.value, }); setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS); } @@ -543,6 +544,7 @@ export default class SettingsPage extends React.Component { options.push( {'Icon theme: '}