У меня есть устаревшее приложение Backbone, которое я начал переписывать в React. Приложение имеет основной вид, содержащий два подпредставления, расположенные вертикально. На верхней панели отображаются некоторые данные, а на нижней - результаты какого-либо алгоритма, принимающего эти данные в качестве входных данных Поскольку у меня много разных источников данных, к каждому из которых применяется свой алгоритм, у меня есть абстрактный базовый класс View, который я затем подклассирую для каждого источника данных, добавляя, декорируя и переопределяя методы по мере необходимости. Примерно так:
// Base View.
const BaseView = Backbone.View.extend({
events: {},
initialize() {
this.subViewA = // instantiate subview...
this.subViewB = // instantiate subview...
},
generateResultData() {
// 'Abstract' method which should be specialised to generate data rendered by subViewB...
},
render() {
// render subviews...
},
});
// Derived View.
const Derived = BaseView.extend({
events: {
// event handlers...
},
add(a, b) {
return a+b;
},
// additional methods...
generateResultData() {
return {
result: this.add(2,2);
}
},
})
Это приводит к поверхностной иерархии многих похожих классов View. Все это ужасно необходимо, но это простой, интуитивно понятный и простой для понимания шаблон, и просто работает . Однако я изо всех сил пытаюсь понять, как добиться того же в React. Учитывая, что подклассы подклассов React.Component
считаются антишаблоном, я, естественно, сфокусировался на композиции, и в частности на компонентах высшего порядка. HOCs (которые я нахожу красивыми, но не интуитивно понятными и часто просто смущающими), кажется, включают добавление общих функций, а не специализацию / уточнение чего-то более общего. Я также рассмотрел возможность передачи более специализированных версий методов Componenet через реквизит. но это просто означает, что я должен снова и снова использовать одно и то же определение компонента:
// General functional component, renders the result of prop function 'foo'.
function GeneralComponent(props) {
const foo = this.props.foo || ()=>"foo";
return (
<div>
<span> { this.props.foo() } </span>
</div>
)
}
// Specialised component 1, overrides 'foo'.
class MySpecialisedComponent extends React.Component {
foo() {
return this.bar()
}
bar() {
return "bar"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
// Specialised component 2, overrides 'foo' and adds another method.
class MyOtherSpecialisedComponent extends React.Component {
foo() {
return this.bar() + this.bar()
}
bar() {
return "bar"
}
baz() {
return "baz"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
Выше приведен очень упрощенный случай, но, по сути, он отражает то, что мне нужно сделать (хотя я бы, конечно, манипулировал состоянием, чего не делает пример, для простоты). Я имею в виду, я мог бы просто делать такие вещи. Но я хочу избежать повторения этого шаблона повсюду. Так есть ли более простой и элегантный способ сделать это?