diff --git a/src/index.tsx b/src/index.tsx index 5b3e76d..7b29c03 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,15 +1,17 @@ -import * as React from 'react'; -import * as codemirror from 'codemirror'; -import {Position} from "codemirror"; +import * as React from "react"; +import * as codemirror from "codemirror"; +import { Position } from "codemirror"; declare let global: any; declare let require: any; -const SERVER_RENDERED = (typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true); +const SERVER_RENDERED = + typeof navigator === "undefined" || + global["PREVENT_CODEMIRROR_RENDER"] === true; let cm; if (!SERVER_RENDERED) { - cm = require('codemirror'); + cm = require("codemirror"); } export interface IDefineModeOptions { @@ -38,10 +40,18 @@ export interface ICodeMirror { cursor?: codemirror.Position; defineMode?: IDefineModeOptions; editorDidConfigure?: (editor: codemirror.Editor) => void; - editorDidMount?: (editor: codemirror.Editor, value: string, cb: () => void) => void; + editorDidMount?: ( + editor: codemirror.Editor, + value: string, + cb: () => void + ) => void; editorWillUnmount?: (lib: any) => void; onBlur?: DomEvent; - onChange?: (editor: codemirror.Editor, data: codemirror.EditorChange, value: string) => void; + onChange?: ( + editor: codemirror.Editor, + data: codemirror.EditorChange, + value: string + ) => void; onContextMenu?: DomEvent; onCopy?: DomEvent; onCursor?: (editor: codemirror.Editor, data: codemirror.Position) => void; @@ -50,29 +60,46 @@ export interface ICodeMirror { onDblClick?: DomEvent; onDragEnter?: DomEvent; onDragLeave?: DomEvent; - onDragOver?: DomEvent + onDragOver?: DomEvent; onDragStart?: DomEvent; onDrop?: DomEvent; - onFocus?: DomEvent - onGutterClick?: (editor: codemirror.Editor, lineNumber: number, gutter: string, event: Event) => void; + onFocus?: DomEvent; + onGutterClick?: ( + editor: codemirror.Editor, + lineNumber: number, + gutter: string, + event: Event + ) => void; onKeyDown?: DomEvent; onKeyPress?: DomEvent; onKeyUp?: DomEvent; onMouseDown?: DomEvent; onPaste?: DomEvent; - onRenderLine?: (editor: codemirror.Editor, line: codemirror.LineHandle, element: HTMLElement) => void; + onRenderLine?: ( + editor: codemirror.Editor, + line: codemirror.LineHandle, + element: HTMLElement + ) => void; onScroll?: (editor: codemirror.Editor, data: codemirror.ScrollInfo) => void; onSelection?: (editor: codemirror.Editor, data: any) => void; onTouchStart?: DomEvent; onUpdate?: (editor: codemirror.Editor) => void; - onViewportChange?: (editor: codemirror.Editor, start: number, end: number) => void; - options?: codemirror.EditorConfiguration - selection?: { ranges: Array, focus?: boolean }; + onViewportChange?: ( + editor: codemirror.Editor, + start: number, + end: number + ) => void; + options?: codemirror.EditorConfiguration; + selection?: { ranges: Array; focus?: boolean }; scroll?: ISetScrollOptions; } export interface IControlledCodeMirror extends ICodeMirror { - onBeforeChange: (editor: codemirror.Editor, data: codemirror.EditorChange, value: string) => void; + onBeforeChange: ( + editor: codemirror.Editor, + data: codemirror.EditorChange, + value: string + ) => void; value: string; } @@ -80,58 +107,104 @@ export interface IUnControlledCodeMirror extends ICodeMirror { detach?: boolean; editorDidAttach?: (editor: codemirror.Editor) => void; editorDidDetach?: (editor: codemirror.Editor) => void; - onBeforeChange?: (editor: codemirror.Editor, data: codemirror.EditorChange, value: string, next: () => void) => void; + onBeforeChange?: ( + editor: codemirror.Editor, + data: codemirror.EditorChange, + value: string, + next: () => void + ) => void; value?: string; } declare interface ICommon { - wire: (props: IControlledCodeMirror | IUnControlledCodeMirror) => void; + wire: ( + prevProps: IControlledCodeMirror | IUnControlledCodeMirror, + props: IControlledCodeMirror | IUnControlledCodeMirror + ) => void; + unwire: (props: IControlledCodeMirror | IUnControlledCodeMirror) => void; apply: (props: IControlledCodeMirror | IUnControlledCodeMirror) => void; - applyNext: (props: IControlledCodeMirror | IUnControlledCodeMirror, next?: IControlledCodeMirror | IUnControlledCodeMirror, preserved?: IPreservedOptions) => void; - applyUserDefined: (props: IControlledCodeMirror | IUnControlledCodeMirror, preserved?: IPreservedOptions) => void; + applyNext: ( + props: IControlledCodeMirror | IUnControlledCodeMirror, + next?: IControlledCodeMirror | IUnControlledCodeMirror, + preserved?: IPreservedOptions + ) => void; + applyUserDefined: ( + props: IControlledCodeMirror | IUnControlledCodeMirror, + preserved?: IPreservedOptions + ) => void; } declare interface IPreservedOptions { - cursor?: codemirror.Position + cursor?: codemirror.Position; } abstract class Helper { public static equals(x: {}, y: {}) { - const ok = Object.keys, tx = typeof x, ty = typeof y; - return x && y && tx === 'object' && tx === ty ? ( - ok(x).length === ok(y).length && - ok(x).every(key => this.equals(x[key], y[key])) - ) : (x === y); + const ok = Object.keys, + tx = typeof x, + ty = typeof y; + return x && y && tx === "object" && tx === ty + ? ok(x).length === ok(y).length && + ok(x).every(key => this.equals(x[key], y[key])) + : x === y; } } class Shared implements ICommon { - private editor: codemirror.Editor; - private props: ICodeMirror; - - constructor(editor, props) { + private eventMappings = { + onBlur: "blur", + onContextMenu: "contextmenu", + onCopy: "copy", + onCursor: "cursorActivity", + onCursorActivity: "cursorActivity", + onCut: "cut", + onDblClick: "dblclick", + onDragEnter: "dragenter", + onDragLeave: "dragleave", + onDragOver: "dragover", + onDragStart: "dragstart", + onDrop: "drop", + onFocus: "focus", + onGutterClick: "gutterClick", + onKeyDown: "keydown", + onKeyPress: "keypress", + onKeyUp: "keyup", + onMouseDown: "mousedown", + onPaste: "paste", + onRenderLine: "renderLine", + onScroll: "scroll", + onSelection: "beforeSelectionChange", + onTouchStart: "touchstart", + onUpdate: "update", + onViewportChange: "viewportChange" + }; + + constructor(editor) { this.editor = editor; - this.props = props; } - delegateCursor(position: codemirror.Position, scroll?: boolean, focus?: boolean) { - + delegateCursor( + position: codemirror.Position, + scroll?: boolean, + focus?: boolean + ) { const doc = this.editor.getDoc() as codemirror.Doc; if (focus) { this.editor.focus(); } - scroll ? doc.setCursor(position) : doc.setCursor(position, null, {scroll: false}); + scroll + ? doc.setCursor(position) + : doc.setCursor(position, null, { scroll: false }); } delegateScroll(coordinates: ISetScrollOptions) { - this.editor.scrollTo(coordinates.x, coordinates.y) + this.editor.scrollTo(coordinates.x, coordinates.y); } delegateSelection(ranges: Array, focus?: boolean) { - const doc = this.editor.getDoc() as codemirror.Doc; doc.setSelections(ranges); @@ -141,15 +214,21 @@ class Shared implements ICommon { } public apply(props: IControlledCodeMirror | IUnControlledCodeMirror) { - // init ranges if (props && props.selection && props.selection.ranges) { - this.delegateSelection(props.selection.ranges, props.selection.focus || false); + this.delegateSelection( + props.selection.ranges, + props.selection.focus || false + ); } // init cursor if (props && props.cursor) { - this.delegateCursor(props.cursor, (props.autoScroll || false), (this.editor.getOption('autofocus') || false)); + this.delegateCursor( + props.cursor, + props.autoScroll || false, + this.editor.getOption("autofocus") || false + ); } // init scroll @@ -158,198 +237,88 @@ class Shared implements ICommon { } } - public applyNext(props: IControlledCodeMirror | IUnControlledCodeMirror, next?: IControlledCodeMirror | IUnControlledCodeMirror, preserved?: any) { - + public applyNext( + props: IControlledCodeMirror | IUnControlledCodeMirror, + next?: IControlledCodeMirror | IUnControlledCodeMirror, + preserved?: any + ) { // handle new ranges if (props && props.selection && props.selection.ranges) { - if (next && next.selection && next.selection.ranges && !Helper.equals(props.selection.ranges, next.selection.ranges)) { - this.delegateSelection(next.selection.ranges, next.selection.focus || false); + if ( + next && + next.selection && + next.selection.ranges && + !Helper.equals(props.selection.ranges, next.selection.ranges) + ) { + this.delegateSelection( + next.selection.ranges, + next.selection.focus || false + ); } } // handle new cursor if (props && props.cursor) { if (next && next.cursor && !Helper.equals(props.cursor, next.cursor)) { - this.delegateCursor(preserved.cursor || next.cursor, (next.autoScroll || false), (next.autoCursor || false)); + this.delegateCursor( + preserved.cursor || next.cursor, + next.autoScroll || false, + next.autoCursor || false + ); } } // handle new scroll if (props && props.scroll) { if (next && next.scroll && !Helper.equals(props.scroll, next.scroll)) { - this.delegateScroll(next.scroll) + this.delegateScroll(next.scroll); } } } - public applyUserDefined(props: IControlledCodeMirror | IUnControlledCodeMirror, preserved?: any) { + public applyUserDefined( + props: IControlledCodeMirror | IUnControlledCodeMirror, + preserved?: any + ) { if (preserved && preserved.cursor) { - this.delegateCursor(preserved.cursor, (props.autoScroll || false), (this.editor.getOption('autofocus') || false)); + this.delegateCursor( + preserved.cursor, + props.autoScroll || false, + this.editor.getOption("autofocus") || false + ); } } - public wire(props: IControlledCodeMirror | IUnControlledCodeMirror) { - - Object.keys(props || {}).filter(p => /^on/.test(p)).forEach(prop => { - switch (prop) { - case 'onBlur': { - (this.editor as any).on('blur', (cm, event) => { - this.props.onBlur(this.editor, event); - }); - } - break; - case 'onContextMenu': { - this.editor.on('contextmenu', (cm, event) => { - this.props.onContextMenu(this.editor, event); - }); - break; - } - case 'onCopy': { - this.editor.on('copy', (cm, event) => { - this.props.onCopy(this.editor, event); - }); - break; - } - case 'onCursor': { - this.editor.on('cursorActivity', (cm) => { - this.props.onCursor(this.editor, this.editor.getDoc().getCursor()); - }); - } - break; - case 'onCursorActivity': { - this.editor.on('cursorActivity', (cm) => { - this.props.onCursorActivity(this.editor); - }); - } - break; - case 'onCut': { - this.editor.on('cut', (cm, event) => { - this.props.onCut(this.editor, event); - }); - break; - } - case 'onDblClick': { - this.editor.on('dblclick', (cm, event) => { - this.props.onDblClick(this.editor, event); - }); - break; - } - case 'onDragEnter': { - this.editor.on('dragenter', (cm, event) => { - this.props.onDragEnter(this.editor, event); - }); - } - break; - case 'onDragLeave': { - this.editor.on('dragleave', (cm, event) => { - this.props.onDragLeave(this.editor, event); - }); - break; - } - case 'onDragOver': { - this.editor.on('dragover', (cm, event) => { - this.props.onDragOver(this.editor, event); - }); + public wire( + prevProps: IControlledCodeMirror | IUnControlledCodeMirror, + props: IControlledCodeMirror | IUnControlledCodeMirror + ) { + Object.keys(props || {}) + .filter(prop => this.eventMappings[prop] !== undefined) + .filter(prop => props[prop] !== prevProps[prop]) + .forEach(prop => { + const event = this.eventMappings[prop]; + + // Get rid of previous listener if present + if (prevProps[prop] !== undefined) { + this.editor.off(event, prevProps[prop]); } - break; - case 'onDragStart': { - this.editor.on('dragstart', (cm, event) => { - this.props.onDragStart(this.editor, event); - }); - break; - } - case 'onDrop': { - this.editor.on('drop', (cm, event) => { - this.props.onDrop(this.editor, event); - }); - } - break; - case 'onFocus': { - (this.editor as any).on('focus', (cm, event) => { - this.props.onFocus(this.editor, event); - }); - } - break; - case 'onGutterClick': { - this.editor.on('gutterClick', (cm, lineNumber, gutter, event) => { - this.props.onGutterClick(this.editor, lineNumber, gutter, event); - }); - } - break; - case 'onKeyDown': { - this.editor.on('keydown', (cm, event) => { - this.props.onKeyDown(this.editor, event); - }); - } - break; - case 'onKeyPress': { - this.editor.on('keypress', (cm, event) => { - this.props.onKeyPress(this.editor, event); - }); - } - break; - case 'onKeyUp': { - this.editor.on('keyup', (cm, event) => { - this.props.onKeyUp(this.editor, event); - }); - } - break; - case 'onMouseDown': { - this.editor.on('mousedown', (cm, event) => { - this.props.onMouseDown(this.editor, event); - }); - break; - } - case 'onPaste': { - this.editor.on('paste', (cm, event) => { - this.props.onPaste(this.editor, event); - }); - break; - } - case 'onRenderLine': { - this.editor.on('renderLine', (cm, line, element) => { - this.props.onRenderLine(this.editor, line, element); - }); - break; - } - case 'onScroll': { - this.editor.on('scroll', (cm) => { - this.props.onScroll(this.editor, this.editor.getScrollInfo()); - }); - } - break; - case 'onSelection': { - this.editor.on('beforeSelectionChange', (cm, data) => { - this.props.onSelection(this.editor, data); - }); - } - break; - case 'onTouchStart': { - this.editor.on('touchstart', (cm, event) => { - this.props.onTouchStart(this.editor, event); - }); - break; - } - case 'onUpdate': { - this.editor.on('update', (cm) => { - this.props.onUpdate(this.editor); - }); - } - break; - case 'onViewportChange': { - this.editor.on('viewportChange', (cm, from, to) => { - this.props.onViewportChange(this.editor, from, to); - }); - } - break; - } - }); + this.editor.on(event, props[prop]); + }); + } + + public unwire(props: IControlledCodeMirror | IUnControlledCodeMirror) { + Object.keys(props || {}) + .filter(prop => this.eventMappings[prop] !== undefined) + .forEach(prop => { + const event = this.eventMappings[prop]; + this.editor.off(event, props[prop]); + }); } } export class Controlled extends React.Component { - /** @internal */ private applied: boolean; /** @internal */ @@ -397,16 +366,21 @@ export class Controlled extends React.Component { /** @internal */ private hydrate(props) { - const _options = props && props.options ? props.options : {}; - const userDefinedOptions = Object.assign({}, cm.defaults, (this.editor as any).options, _options); + const userDefinedOptions = Object.assign( + {}, + cm.defaults, + (this.editor as any).options, + _options + ); - const optionDelta = Object.keys(userDefinedOptions).some(key => this.editor.getOption(key) !== userDefinedOptions[key]); + const optionDelta = Object.keys(userDefinedOptions).some( + key => this.editor.getOption(key) !== userDefinedOptions[key] + ); if (optionDelta) { Object.keys(userDefinedOptions).forEach(key => { - if (_options.hasOwnProperty(key)) { if (this.editor.getOption(key) !== userDefinedOptions[key]) { this.editor.setOption(key, userDefinedOptions[key]); @@ -416,23 +390,24 @@ export class Controlled extends React.Component { }); } if (!this.hydrated) { - this.deferred ? this.resolveChange() : this.initChange(props.value || '') + this.deferred ? this.resolveChange() : this.initChange(props.value || ""); } this.hydrated = true; } /** @internal */ private initChange(value) { - this.emulating = true; const doc = this.editor.getDoc(); const lastLine = doc.lastLine(); const lastChar = doc.getLine(doc.lastLine()).length; - doc.replaceRange(value || '', - {line: 0, ch: 0}, - {line: lastLine, ch: lastChar}); + doc.replaceRange( + value || "", + { line: 0, ch: 0 }, + { line: lastLine, ch: lastChar } + ); this.mirror.setValue(value); doc.clearHistory(); @@ -443,17 +418,21 @@ export class Controlled extends React.Component { /** @internal */ private resolveChange() { - this.emulating = true; const doc = this.editor.getDoc(); - if (this.deferred.origin === 'undo') { + if (this.deferred.origin === "undo") { doc.undo(); - } else if (this.deferred.origin === 'redo') { + } else if (this.deferred.origin === "redo") { doc.redo(); } else { - doc.replaceRange(this.deferred.text, this.deferred.from, this.deferred.to, this.deferred.origin); + doc.replaceRange( + this.deferred.text, + this.deferred.from, + this.deferred.to, + this.deferred.origin + ); } this.emulating = false; @@ -462,17 +441,21 @@ export class Controlled extends React.Component { /** @internal */ private mirrorChange(deferred) { - const doc = this.editor.getDoc(); - if (deferred.origin === 'undo') { + if (deferred.origin === "undo") { doc.setHistory(this.mirror.getHistory()); this.mirror.undo(); - } else if (deferred.origin === 'redo') { + } else if (deferred.origin === "redo") { doc.setHistory(this.mirror.getHistory()); this.mirror.redo(); } else { - this.mirror.replaceRange(deferred.text, deferred.from, deferred.to, deferred.origin); + this.mirror.replaceRange( + deferred.text, + deferred.from, + deferred.to, + deferred.origin + ); } return this.mirror.getValue(); @@ -480,7 +463,6 @@ export class Controlled extends React.Component { /** @internal */ public componentDidMount() { - if (SERVER_RENDERED) return; if (this.props.defineMode) { @@ -491,21 +473,19 @@ export class Controlled extends React.Component { this.editor = cm(this.ref) as codemirror.Editor; - this.shared = new Shared(this.editor, this.props); + this.shared = new Shared(this.editor); - this.mirror = (cm as any)(() => { - }); + this.mirror = (cm as any)(() => {}); - this.editor.on('electricInput', () => { + this.editor.on("electricInput", () => { this.mirror.setHistory(this.editor.getDoc().getHistory()); }); - this.editor.on('cursorActivity', () => { + this.editor.on("cursorActivity", () => { this.mirror.setCursor(this.editor.getDoc().getCursor()); }); - this.editor.on('beforeChange', (cm, data) => { - + this.editor.on("beforeChange", (cm, data) => { if (this.emulating) { return; } @@ -520,8 +500,7 @@ export class Controlled extends React.Component { this.props.onBeforeChange(this.editor, this.deferred, phantomChange); }); - this.editor.on('change', (cm, data) => { - + this.editor.on("change", (cm, data) => { if (!this.mounted) { return; } @@ -539,23 +518,30 @@ export class Controlled extends React.Component { this.mounted = true; - this.shared.wire(this.props); + this.shared.wire({}, this.props); - if (this.editor.getOption('autofocus')) { + if (this.editor.getOption("autofocus")) { this.editor.focus(); } if (this.props.editorDidMount) { - this.props.editorDidMount(this.editor, this.editor.getValue(), this.initCb); + this.props.editorDidMount( + this.editor, + this.editor.getValue(), + this.initCb + ); } } + public componentDidUpdate(prevProps) { + this.shared.wire(prevProps, this.props); + } + /** @internal */ public componentWillReceiveProps(nextProps) { - if (SERVER_RENDERED) return; - let preserved: IPreservedOptions = {cursor: null}; + let preserved: IPreservedOptions = { cursor: null }; if (nextProps.value !== this.props.value) { this.hydrated = false; @@ -578,7 +564,6 @@ export class Controlled extends React.Component { /** @internal */ public componentWillUnmount() { - if (SERVER_RENDERED) return; if (this.props.editorWillUnmount) { @@ -588,22 +573,25 @@ export class Controlled extends React.Component { /** @internal */ public shouldComponentUpdate(nextProps, nextState) { - return !SERVER_RENDERED + return !SERVER_RENDERED; } /** @internal */ public render() { - if (SERVER_RENDERED) return null; - let className = this.props.className ? `react-codemirror2 ${this.props.className}` : 'react-codemirror2'; + let className = this.props.className + ? `react-codemirror2 ${this.props.className}` + : "react-codemirror2"; - return
this.ref = self}/> + return
(this.ref = self)} />; } } -export class UnControlled extends React.Component { - +export class UnControlled extends React.Component< + IUnControlledCodeMirror, + any +> { /** @internal */ private applied: boolean; /** @internal */ @@ -651,10 +639,16 @@ export class UnControlled extends React.Component /** @internal */ private hydrate(props) { - const _options = props && props.options ? props.options : {}; - const userDefinedOptions = Object.assign({}, cm.defaults, (this.editor as any).options, _options); - const optionDelta = Object.keys(userDefinedOptions).some(key => this.editor.getOption(key) !== userDefinedOptions[key]); + const userDefinedOptions = Object.assign( + {}, + cm.defaults, + (this.editor as any).options, + _options + ); + const optionDelta = Object.keys(userDefinedOptions).some( + key => this.editor.getOption(key) !== userDefinedOptions[key] + ); if (optionDelta) { Object.keys(userDefinedOptions).forEach(key => { @@ -671,9 +665,11 @@ export class UnControlled extends React.Component const lastLine = doc.lastLine(); const lastChar = doc.getLine(doc.lastLine()).length; - doc.replaceRange(props.value || '', - {line: 0, ch: 0}, - {line: lastLine, ch: lastChar}); + doc.replaceRange( + props.value || "", + { line: 0, ch: 0 }, + { line: lastLine, ch: lastChar } + ); } this.hydrated = true; @@ -681,10 +677,9 @@ export class UnControlled extends React.Component /** @internal */ public componentDidMount() { - if (SERVER_RENDERED) return; - this.detached = (this.props.detach === true); + this.detached = this.props.detach === true; if (this.props.defineMode) { if (this.props.defineMode.name && this.props.defineMode.fn) { @@ -694,27 +689,30 @@ export class UnControlled extends React.Component this.editor = cm(this.ref) as codemirror.Editor; - this.shared = new Shared(this.editor, this.props); - - this.editor.on('beforeChange', (cm, data) => { + this.shared = new Shared(this.editor); + this.editor.on("beforeChange", (cm, data) => { if (this.props.onBeforeChange) { - this.props.onBeforeChange(this.editor, data, this.editor.getValue(), this.onBeforeChangeCb) + this.props.onBeforeChange( + this.editor, + data, + this.editor.getValue(), + this.onBeforeChangeCb + ); } }); - this.editor.on('change', (cm, data) => { - + this.editor.on("change", (cm, data) => { if (!this.mounted || !this.props.onChange) { return; } if (this.props.onBeforeChange) { if (this.continueChange) { - this.props.onChange(this.editor, data, this.editor.getValue()) + this.props.onChange(this.editor, data, this.editor.getValue()); } } else { - this.props.onChange(this.editor, data, this.editor.getValue()) + this.props.onChange(this.editor, data, this.editor.getValue()); } }); @@ -726,26 +724,33 @@ export class UnControlled extends React.Component this.mounted = true; - this.shared.wire(this.props); + this.shared.wire({}, this.props); this.editor.getDoc().clearHistory(); if (this.props.editorDidMount) { - this.props.editorDidMount(this.editor, this.editor.getValue(), this.initCb); + this.props.editorDidMount( + this.editor, + this.editor.getValue(), + this.initCb + ); } } + public componentDidUpdate(prevProps) { + this.shared.wire(prevProps, this.props); + } + /** @internal */ public componentWillReceiveProps(nextProps) { - - if (this.detached && (nextProps.detach === false)) { + if (this.detached && nextProps.detach === false) { this.detached = false; if (this.props.editorDidAttach) { this.props.editorDidAttach(this.editor); } } - if (!this.detached && (nextProps.detach === true)) { + if (!this.detached && nextProps.detach === true) { this.detached = true; if (this.props.editorDidDetach) { this.props.editorDidDetach(this.editor); @@ -754,7 +759,7 @@ export class UnControlled extends React.Component if (SERVER_RENDERED || this.detached) return; - let preserved: IPreservedOptions = {cursor: null}; + let preserved: IPreservedOptions = { cursor: null }; if (nextProps.value !== this.props.value) { this.hydrated = false; @@ -781,17 +786,17 @@ export class UnControlled extends React.Component /** @internal */ public componentWillUnmount() { - if (SERVER_RENDERED) return; if (this.props.editorWillUnmount) { this.props.editorWillUnmount(cm); } + + this.shared.unwire(this.props); } /** @internal */ public shouldComponentUpdate(nextProps, nextState) { - let update = true; if (SERVER_RENDERED) update = false; @@ -802,11 +807,12 @@ export class UnControlled extends React.Component /** @internal */ public render() { - if (SERVER_RENDERED) return null; - let className = this.props.className ? `react-codemirror2 ${this.props.className}` : 'react-codemirror2'; + let className = this.props.className + ? `react-codemirror2 ${this.props.className}` + : "react-codemirror2"; - return
this.ref = self}/> + return
(this.ref = self)} />; } }