React Knockout BindingHandler

by luggage66

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Enter Name: <input data-bind="value: name, valueUpdate: 'afterkeydown'" /> <br />

You Entered:
<div data-bind="react: renderSomeReactComponent"></div>

Babel + JSX

const reactBindingHandler = {
    init(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // make sure we cleanup, later.
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            ReactDOM.unmountComponentAtNode(element);
        });

        // and tell knockout to keep it's grubby mitts out of the react-generated DOM
        return { controlsDescendantBindings: true };
    },
    update(element, valueAccessor, allBindings, viewModel, bindingContext) {
        const renderFn = ko.unwrap(valueAccessor());

        // call the function provided. Assuming the function reads observables,
        // they will be observed so that this component updates.
        const componentTree = renderFn.call(viewModel);

        // (re)render.
        ReactDOM.render(componentTree, element);
    }
};

ko.bindingHandlers.react = reactBindingHandler;

class MyViewModel {
  constructor() {
    this.name = ko.observable('Jimbo');
  }
  
  // will re-render then observable change.
  renderSomeReactComponent() {
    return <p>{this.name()}</p>;
  }
}

let myViewModel = new MyViewModel();

ko.applyBindings(myViewModel);