Javascript 在KnockoutJS中使用React组件

Javascript 在KnockoutJS中使用React组件,javascript,reactjs,knockout.js,Javascript,Reactjs,Knockout.js,我们有一个大型web应用程序,主要是使用KnockoutJS构建的。我正在研究是否有可能迁移到React,但需要重写整个应用程序。我的想法是使用自下而上的方法:从逐个替换基本构建块开始 我受到一些人的启发,在KnockoutJS绑定处理程序中调用ReactDOM.render: ko.bindingHandlers.react = { init() { return {controlsDescendantBindings: true}; }, update

我们有一个大型web应用程序,主要是使用KnockoutJS构建的。我正在研究是否有可能迁移到React,但需要重写整个应用程序。我的想法是使用自下而上的方法:从逐个替换基本构建块开始

我受到一些人的启发,在KnockoutJS绑定处理程序中调用ReactDOM.render:

ko.bindingHandlers.react = {
    init() {
        return {controlsDescendantBindings: true};
    },
    update(element, valueAccessor) {
        const {component, props} = valueAccessor();
        ReactDOM.render(React.createElement(component, props), element);
    }
};
Knockout有自己的依赖项跟踪系统,因此每当某些数据发生更改时,它都会调用update方法

它可以完美地工作,并且重新渲染组件以反映对数据的任何更改。但是,当在React事件处理程序中更新数据时,它会崩溃。例如,该组件不能按预期工作:

const Input = function ({value}) {
    return <input type="text" 
                  value={value()} 
                  onChange={e => value(e.target.value)}/>;
}
const输入=函数({value}){
返回值(e.target.value)}/>;
}
注意:本例中的值是ko.observable,像在事件处理程序中那样调用它将导致调用bindingHandler的update方法,后者反过来调用ReactDOM.render。但是,此渲染仅工作一次,之后组件停止更新

。单击框并尝试键入内容。经过一次更新后,组件的函数停止调用

编辑:我认为问题在于对ReactDOM.render的第二次调用(当用户在onChange处理程序中更新值时)是不同步的。这意味着Knockout的依赖项检测无法工作,任何后续调用都不再调用绑定处理程序的update方法

这能以某种方式避免吗?

对我来说:

 update(element, valueAccessor) {
    const {component, props} = valueAccessor();
    props.value(props.value());
    ReactDOM.render(React.createElement(component, props), element);
}

如果刷新您的
可观察对象
,它将工作,但不幸的是,我不知道如何工作。

正如我所猜测的,问题似乎是ReactDOM.render在某些情况下是异步的-在这种情况下,当从React中的事件处理程序调用时

这意味着,如果在更新方法本身中取消引用任何依赖的观测值,那么Knockout的依赖项跟踪机制将按预期工作。这就是为什么Gawel1908建议的修改使它工作的原因-不是因为值是“重置”,而是因为props.value被取消引用

我决定改为使用约定:始终在valueAccessor本身中展开任何此类观察:

<div data-bind="react: { component: Input, props: { value: val(), setValue: val }}">
</div>

并且不要在组件中展开它:

const Input = function ({value, setValue}) {
  return <input 
           type="text" 
           value={value} 
           onChange={e => setValue(e.target.value)}/>;
}
const Input=function({value,setValue}){
返回setValue(e.target.value)}/>;
}

我认为这证明了我之前认为可能是错误的地方——从事件处理程序调用ReactDOM.render时,它不是同步的。我可能可以根据这些信息制定一个解决方案。如何处理react组件的清理?我也在使用同样的方法,当我移动到另一个页面时,我仍然看到上一个页面中呈现的组件