diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 759ccdd10d..6019b65ec1 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,143 +1,129 @@ +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; -import React from 'react'; import CodeMirror from 'codemirror'; import { Encode } from 'console-feed'; import RightArrowIcon from '../../../images/right-arrow.svg'; import { dispatchMessage, MessageTypes } from '../../../utils/dispatcher'; -// heavily inspired by -// https://github.com/codesandbox/codesandbox-client/blob/92a1131f4ded6f7d9c16945dc7c18aa97c8ada27/packages/app/src/app/components/Preview/DevTools/Console/Input/index.tsx +function ConsoleInput(props) { + const [commandHistory, setCommandHistory] = useState([]); + const [commandCursor, setCommandCursor] = useState(-1); + const codemirrorContainerRef = useRef(null); + const cmRef = useRef(null); -class ConsoleInput extends React.Component { - constructor(props) { - super(props); - this.state = { - commandHistory: [], - commandCursor: -1 - }; - } - - componentDidMount() { - this._cm = CodeMirror(this.codemirrorContainer, { - // eslint-disable-line - theme: `p5-${this.props.theme}`, + useEffect(() => { + cmRef.current = CodeMirror(codemirrorContainerRef.current, { + theme: `p5-${props.theme}`, scrollbarStyle: null, keymap: 'sublime', mode: 'javascript', - inputStyle: 'contenteditable' + inputStyle: 'contenteditable', }); - this._cm.on('keydown', (cm, e) => { + cmRef.current.on('keydown', (cm, e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); e.stopPropagation(); const value = cm.getValue(); - if (value.trim(' ') === '') { + if (value.trim() === '') { return false; } const messages = [ - { log: Encode({ method: 'command', data: [value] }) } + { log: Encode({ method: 'command', data: [value] }) }, ]; const consoleEvent = [{ method: 'command', data: [value] }]; dispatchMessage({ type: MessageTypes.EXECUTE, payload: { source: 'console', - messages - } + messages, + }, }); - this.props.dispatchConsoleEvent(consoleEvent); + props.dispatchConsoleEvent(consoleEvent); cm.setValue(''); - this.setState((state) => ({ - commandCursor: -1, - commandHistory: [value, ...state.commandHistory] - })); + setCommandCursor(-1); + setCommandHistory((prevHistory) => [value, ...prevHistory]); } else if (e.key === 'ArrowUp') { - const lineNumber = this._cm.getDoc().getCursor().line; + const lineNumber = cm.getDoc().getCursor().line; if (lineNumber !== 0) { return false; } - this.setState((state) => { + setCommandCursor((prevCursor) => { const newCursor = Math.min( - state.commandCursor + 1, - state.commandHistory.length - 1 + prevCursor + 1, + commandHistory.length - 1 ); - this._cm.getDoc().setValue(state.commandHistory[newCursor] || ''); - const cursorPos = this._cm.getDoc().getLine(0).length - 1; - this._cm.getDoc().setCursor({ line: 0, ch: cursorPos }); - return { commandCursor: newCursor }; + cm.getDoc().setValue(commandHistory[newCursor] || ''); + const cursorPos = cm.getDoc().getLine(0).length - 1; + cm.getDoc().setCursor({ line: 0, ch: cursorPos }); + return newCursor; }); } else if (e.key === 'ArrowDown') { - const lineNumber = this._cm.getDoc().getCursor().line; - const lineCount = this._cm.getValue().split('\n').length; + const lineNumber = cm.getDoc().getCursor().line; + const lineCount = cm.getValue().split('\n').length; if (lineNumber + 1 !== lineCount) { return false; } - this.setState((state) => { - const newCursor = Math.max(state.commandCursor - 1, -1); - this._cm.getDoc().setValue(state.commandHistory[newCursor] || ''); - const newLineCount = this._cm.getValue().split('\n').length; - const newLine = this._cm.getDoc().getLine(newLineCount); + setCommandCursor((prevCursor) => { + const newCursor = Math.max(prevCursor - 1, -1); + cm.getDoc().setValue(commandHistory[newCursor] || ''); + const newLineCount = cm.getValue().split('\n').length; + const newLine = cm.getDoc().getLine(newLineCount); const cursorPos = newLine ? newLine.length - 1 : 1; - this._cm.getDoc().setCursor({ line: lineCount, ch: cursorPos }); - return { commandCursor: newCursor }; + cm.getDoc().setCursor({ line: lineCount, ch: cursorPos }); + return newCursor; }); } return true; }); - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; - } + cmRef.current.getWrapperElement().style['font-size'] = `${props.fontSize}px`; + }, [props.theme, props.fontSize]); - componentDidUpdate(prevProps) { - this._cm.setOption('theme', `p5-${this.props.theme}`); - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; - this._cm.refresh(); - } + useEffect(() => { + if (cmRef.current) { + cmRef.current.setOption('theme', `p5-${props.theme}`); + cmRef.current.getWrapperElement().style['font-size'] = `${props.fontSize}px`; + cmRef.current.refresh(); + } + }, [props.theme, props.fontSize]); - componentWillUnmount() { - this._cm = null; - } + useEffect(() => { + return () => { + if (cmRef.current) { + cmRef.current = null; + } + }; + }, []); - render() { - return ( -