Inferno: Div with contenteditable=true & onInput - Bug

Created on 14 Aug 2017  Â·  5Comments  Â·  Source: infernojs/inferno


Issue Template

Observed Behaviour

By creating a textarea along with an onInput event we get this behavior:

vgfcjfft7v

Expected Current Behaviour

A normal textarea

Code

Here is the code to replicate:

import Component from 'inferno-component';
class App extends Component {

constructor(props) {
  super(props);
    this.state = {
      text: "",
    }
  }

  render() {
    return (
      <div className="App" contenteditable="true" onInput={event => this.setState({text: event.target.innerText})}>
        {this.state.text}
      </div>
    );
  }
}

export default App;

Or fork this repo: https://github.com/tloriato/inferno-issue

Inferno Metadata
macOS
Chrome

bug

Most helpful comment

I had a look at this and it is indeed bug. I believe this will be fixed in next major version without any extra changes. Its caused by normalization that changes the flow to use keyed algorithm.

Here the workaround you can use before v4 is ready:

  render() {
    return (
      <div hasNonKeyedChildren noNormalize className="App" contenteditable="true" onInput={event => {
        this.setState({text: event.target.innerText})
      }}>
        {<br /> || this.state.text}
      </div>
    );
  }

I don't know why <br/> is needed when content is empty, but at least Chrome seems to add it there. This workaround tells Inferno to always use nonKeyed algorithm and skip normalization process.

Edit: This works only because hasNonKeyedChildren will skip patching process, but its not acting as controlled element, but instead shows what user wrote there.

All 5 comments

Inferno does not have any extra handling for contentEditable elements, I believe ( without looking into this ) its native browser behavior. textArea / inputs / select have special handling and thus they are different.

I had a look at this and it is indeed bug. I believe this will be fixed in next major version without any extra changes. Its caused by normalization that changes the flow to use keyed algorithm.

Here the workaround you can use before v4 is ready:

  render() {
    return (
      <div hasNonKeyedChildren noNormalize className="App" contenteditable="true" onInput={event => {
        this.setState({text: event.target.innerText})
      }}>
        {<br /> || this.state.text}
      </div>
    );
  }

I don't know why <br/> is needed when content is empty, but at least Chrome seems to add it there. This workaround tells Inferno to always use nonKeyed algorithm and skip normalization process.

Edit: This works only because hasNonKeyedChildren will skip patching process, but its not acting as controlled element, but instead shows what user wrote there.

This part never branches {<br /> || this.state.text} even when this.state.text is not empty after setState({text: '...'}), so you run into a similar problem when it does.

Seeing as it's not a textarea input i also think this is expected behavior – that is you won't get normal textarea behavior with a contentEditable div.

@thysultan true I dont know what I was thinking, some brain fart :D

This is now fixed in dev, fix will be available in next release.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

trueadm picture trueadm  Â·  25Comments

ilyaigpetrov picture ilyaigpetrov  Â·  21Comments

cvg1 picture cvg1  Â·  21Comments

darsain picture darsain  Â·  47Comments

thepian picture thepian  Â·  20Comments