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