3

I'm just trying to create a react component wrapping the CodeMirror (4.1) editor.

I came across this problem for which there is a workround via forcing a refresh once the component has loaded, but I'm not quite sure of the workflow I need to achieve this when react is added into the picture.

The suggestion is that to overcome the error I would need to

"Call .refresh() after resizing the wrapping container."

My code is currently as follows in the Editor component:

  function ($, React, CodeMirror) {

    return React.createClass({

      render: function () {
        console.log("render-editarea");
        return (
          <textarea id="editarea">
-- Comment here
USE [All Data Items];
SELECT ID FROM [Test Event]
          </textarea>
        )
      },

      componentDidMount: function () { 
        var onExecute = this.props.onExecute;
        var editorNode = document.getElementById("editarea");
        console.log("componentDidUpdate-editarea:" + editorNode); 
        var editor = CodeMirror.fromTextArea(editorNode, {        
          lineNumbers: true,
          matchBrackets: true,
          indentUnit: 4,
          mode: "text/x-mssql",
          extraKeys: {"Ctrl-E": function(cm) {    
            console.log(editor.getValue());
            onExecute(editor.getValue());
          }}
        });
      },

and it is loaded via the Render function of the parent component

I have tried

  • hooking the window resize event (as shown in the React manual) in the editor component.
  • forcing a refresh in the parent component's componentDidMount function using $("#editarea").refresh();

but neither of these appeared to work

So I'd be grateful if someone could show me the right way to do it.

Many thx

Aliaksandr Sushkevich
  • 11,550
  • 7
  • 37
  • 44
Simon Woods
  • 2,223
  • 4
  • 27
  • 34

2 Answers2

2

So this post helped me. The .refresh() was a function on CodeMirror which I hadn't fully understood. I used the method as suggested in that post in the parents componentDidLoad event.

componentDidMount: function () {              
  $('.CodeMirror').each(function(i, el){
    el.CodeMirror.refresh();
  });        
},
Community
  • 1
  • 1
Simon Woods
  • 2,223
  • 4
  • 27
  • 34
  • 2
    It's best to not be using IDs in React components. It makes assumptions about the rest of the page (e.g. that there is only one editor, and that no other component will be using that ID). You can get the component's DOM node by using `this.getDOMNode()` and do things from there. – Brigand May 19 '14 at 23:04
  • Thx vm. Could you just confirm that you mean that I should reference the CodeMirror node via a ref (as opposed to replacing the id of the textarea in the render event). Thx again. S – Simon Woods May 20 '14 at 05:33
  • 1
    Here's an example [CodeMirror component](https://github.com/brigand/react-edit/blob/master/src/jsx/common/codemirror.jsx#L28-L34). – Brigand May 20 '14 at 21:45
2

Use the ref attribute to reference rendered nodes rather than IDs or DOM selectors:

function ($, React, CodeMirror) {

  return React.createClass({

    render: function () {
      console.log("render-editarea");
      return (
        <textarea ref="editarea">
-- Comment here
USE [All Data Items];
SELECT ID FROM [Test Event]
        </textarea>
      )
    },

    componentDidMount: function () { 
      var onExecute = this.props.onExecute;
      var editorNode = this.refs.editarea;
      console.log("componentDidUpdate-editarea:" + editorNode); 
      var editor = CodeMirror.fromTextArea(editorNode, {        
        lineNumbers: true,
        matchBrackets: true,
        indentUnit: 4,
        mode: "text/x-mssql",
        extraKeys: {"Ctrl-E": function(cm) {    
          console.log(editor.getValue());
          onExecute(editor.getValue());
        }}
      });
    },
Ross Allen
  • 43,772
  • 14
  • 97
  • 95