score:1

here is a nice way to make a contentEditable div with html and onChange props. i used that with emojione's shortnameToImage function.

here is a working codepen

the styles can be added to ContentEditable props if you want them to come from the state

the only thing that needs to be fixed is the caret position after an emoji is added.

class Application extends React.Component {
  state = {
    value: "Start Writing Here"
  };

  render() {
    return (
      <ContentEditable
        html={emojione.shortnameToImage(this.state.value)}
        onChange={this._onChange}
      />
    );
  }

  _onChange = e => {
    this.setState({ value: e.target.value });
  };
}

var ContentEditable = React.createClass({
  render: function() {
    return (
      <div
        contentEditable
        className="message-input"
        onInput={this.emitChange}
        onBlur={this.emitChange}
        dangerouslySetInnerHTML={{ __html: this.props.html }}
      />
    );
  },

  shouldComponentUpdate: function(nextProps) {
    return nextProps.html !== this.getDOMNode().innerHTML;
  },

  componentDidUpdate: function() {
    if (this.props.html !== this.getDOMNode().innerHTML) {
      this.getDOMNode().innerHTML = this.props.html;
    }
  },

  emitChange: function() {
    var html = this.getDOMNode().innerHTML;

    if (this.props.onChange && html !== this.lastHtml) {
      this.props.onChange({ target: { value: html } });
    }

    this.lastHtml = html;
  }
});

React.render(<Application />, document.getElementById("app"));
html, body {
  height: 100%
}

.message-input {
  width: 100%;
  height: 100%;
  font-size: 30px;
}

.emojione {
  height: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.min.js"></script>
<div id="app"></div>

score:1

I have used emojione and this code snippet to basically come up with a very non-react solution as shown below. Hope it helps.

import React from 'react';
import {render} from 'react-dom';
import emojione from 'emojione';

class App extends React.Component {

    constructor(props) {
        super(props);
    }

    updateText = () => {
        const html = emojione.shortnameToImage(this.refs.inputDiv.innerHTML);
        let sel, range;

        if (window.getSelection) {
            // IE9 and non-IE
            sel = window.getSelection();

            if (sel.getRangeAt && sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.deleteContents();

                // Range.createContextualFragment() would be useful here but is
                // non-standard and not supported in all browsers (IE9, for one)
                let el = this.refs.inputDiv;
                el.innerHTML = html;
                let frag = document.createDocumentFragment(), node, lastNode;

                while ((node = el.firstChild)) {
                    lastNode = frag.appendChild(node);
                }
                range.insertNode(frag);

                // Preserve the selection
                if (lastNode) {
                    range = range.cloneRange();
                    range.setStartAfter(lastNode);
                    range.collapse(true);
                    sel.removeAllRanges();
                    sel.addRange(range);
                }
            }
        } else if (document.selection && document.selection.type !== "Control") {
            // IE < 9
            document.selection.createRange().pasteHTML(html);
        }
    };


    render() {
        return (
            <div ref="inputDiv" contentEditable onInput={this.updateText}/>
        );
    }

}

render(<App/>, document.getElementById('root'));

Here is the working example https://codesandbox.io/s/ol2lmkqqlq


Related Query

More Query from same tag