1

JS Bin Available here

I have a component called ComponentB for which I want to get key down events:

var ComponentB = React.createClass({

  render: function() {
    return (
       <div 
           contentEditable 
           onKeyDown={this.handleKeyDown}>{this.props.data}</div>
    );
  },
  handleKeyDown: function(e) {
     console.log("B: " + e.type +"-" + e.which);
  }
});

I can get those events if this ComponentB is directly under the main/App component.

If I try to embed this component inside another component (componentA) I don't receive those events anymore (this.props.lines is an array of 3 strings) :

var ComponentA = React.createClass({
    render: function(){
        return (
          <div
            contentEditable>
            { 
              this.props.lines.map(function(line,i) {
                return <ComponentB key={i} data={line} />  
              })
            }             
          </div>
          );
    }
});

The associated JS BIN shows this behavior : if you try to edit the lines in the component A section. no event will be emitted but they will if you edit the sinbgle instance of componentB below...

Looks to me like a bug in react.js but wanted to check here first.

1
  • 1
    It seems to be a problem with nested contentEditable elements. Remove contentEditable from ComponentA, and it works as you expect. Commented Jul 24, 2014 at 5:42

1 Answer 1

6

As @ssorallen said in a comment, you can't have nested contentEditable elements, with or without react.

It seems to be a problem with nested contentEditable elements. Remove contentEditable from ComponentA, and it works as you expect.

One of the reasons this doesn't work, is because React doesn't really support contentEditable. Basically it sets the attribute, but it can't sensibly render into the contentEditable because when it tries to update it... the DOM has changed without its knowledge (which throws an error).

Rather you should treat contentEditable elements like an input element, which doesn't have children. Instead you update the innerHTML (see renderComponentToString and dangerouslySetInnerHTML) and listen to onInput events to get changes. See Stack Overflow: onChange event for contentEditable for details on how this works.

A proper handling of contentEditable has been discussed briefly, but no solution was arrived at. Feel free to suggest good ways to handle it.

Sign up to request clarification or add additional context in comments.

1 Comment

Indeed, if I remove contentEditable from componentA I get the keyboard event notifications from componentB. The unfortunate side effect, is that the arrow navigation doesn't work after this change: the arrows left and down don't automatically move between the different divs - this makes sense as ComponentA is no more editable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.