У нас есть большое веб-приложение, в основном построенное с использованием Knockout JS. Я смотрю, есть ли возможность перейти на React, но таким способом, который требует переписывания всего приложения. Моя идея состояла в том, чтобы использовать подход «снизу вверх»: начните с замены базовых c строительных блоков по одному.
Я был вдохновлен некоторыми предыдущими работами , чтобы вызвать ReactDOM.render внутри обработчик привязки Knockout JS:
ko.bindingHandlers.react = {
init() {
return {controlsDescendantBindings: true};
},
update(element, valueAccessor) {
const {component, props} = valueAccessor();
ReactDOM.render(React.createElement(component, props), element);
}
};
Knockout имеет собственную систему отслеживания зависимостей, поэтому он будет вызывать метод обновления при каждом изменении некоторых данных.
Он отлично работает, и компонент перерисовывается для отражения любых изменений данных. Однако он ломается, когда данные обновляются в обработчике событий React. Например, этот компонент не работает должным образом:
const Input = function ({value}) {
return <input type="text"
value={value()}
onChange={e => value(e.target.value)}/>;
}
Примечание: значение в этом случае является ko.observable, и его вызов как в обработчике событий вызовет метод обновления bindingHandler, который в свою очередь вызывает ReactDOM.render. Однако этот рендеринг работает только один раз, после чего компонент прекращает обновление.
Проблема демонстрируется в этом CodePen . Нажмите на поле и попробуйте что-нибудь напечатать. Проходит одно обновление, после чего функция компонента перестает вызываться.
Редактирование: я считаю, что проблема заключается во втором вызове ReactDOM.render (когда значение обновляется пользователем в обработчике onChange) не синхронно. Это означает, что обнаружение зависимостей Knockout не может работать, и любые последующие вызовы больше не вызывают метод обновления обработчика привязки.
Можно ли это как-то обойти?