(псевдо)Спадкування для компонентів ReactJS

Я хочу написати коротенький пост, про те, як я вирішив проблему успадкування в ReactJS. Зазвичай, на форумах, люди радять використовувати міксини для наслідування функціоналу, але, по-моєму, це не зовсім правильно. Все-таки трэйты/міксини і класи це не одне й те ж, та ще і із-за можливості множинного спадкування можуть виникати ось такі казуси:

var A = {
doStuff (){}
}

var B = {
doStuff (){}
}

var C = React.createClass({
mixins: [A, B]
});
//упс... помилка, тому що React не може вирішити, який з doStuff успадкувати



До того ж, міксини не дозволяють робити стандартні ООПешные фішки на зразок перезапису методів(method override):

var A = {
doStuff (){}
}

var C = React.createClass({
mixins: [A],
doStuff (){
//неа, не вийде
}
});


А без цього, природно, не спрацює і розширення функціоналу як у «дорослих» ООП мовами:

doStuff (){
super.doStuff()
//додатковий функціонал
}


Звичайно, класи ES6 вирішать цю проблему, і команда ReactJS до цього готується, якщо судити по постам на їх блозі, але чекати ES6 доведеться як другого пришестя, а потім, доведеться ще почекати поки не вимруть старі Інтернет Эксплореры без підтримки ES6.
Отже, я хочу вам запропонувати альтернативний метод, який і сам використовую, але для цього вам знадобляться:
1) Система модулів/залежностей: RequireJS/Browserify/WebPack/що там ще зараз в моді. Якщо ви не користуєтеся/не знаєте що таке JavaScript модулі, що ж, саме час дізнатися.
2) Яка-небудь функція/ліба для глибокого копіювання об'єктів, наприклад, jQuery.extend, _.extend і т. п.

Отже, я пишу модулі своїх компонент наступним чином:

var React = require('react');
var Human = {
whoAreYou (){
return "i'm a human";
}

whatDoYouDo (){
return "i'm just chilling";
}

render (){
return (
<h1>{this.whoAreYou()}<small>{this.whatDoYouDo()}</small></h1>
)
}
}

module.exports = {
Class: Human,
Component: React.createClass(Human)
}


Фішка в тому, що я експортують не тільки функції, але і «чистий» об'єкт, з якого ця компонента створюється, таким чином, коли мені треба використовувати просто компоненту <Human/>, я беру полі Component з експорту мого модуля:

var Human = require('human').Component;


А от коли мені треба від мого модуля успадкувати, і тут починається найцікавіше, я використовую поле Class:

var React = require('react');
var Parent = require('human').Class;
var Programmer = {};
jQuery.extend(true, Programmer, Parent, {
whoAreYou (){
return Parent.whoAreYou.apply(this) + " and a programmer";//виклик методу з батьків!
}

whatDoYouDo (){
//перезапис методу повністю
return "I write code";
}

drinkCoffee (){
//додавання нового методу
console.log('*sip*');
}
});


Природно, цей модуль я теж експортують згідно вищеописаної «конвенції»:

module.exports = {
Class: Programmer,
Component: React.createClass(Programmer)
}


І тепер його можна використовувати у програмі:

var Programmer = require('programmer').Component;


Ну, або наслідувати/розширювати далі, наприклад, в JuniorDeveloper.
І на цьому все, це був мій коротенький пост про милицю (псевдо)спадкування в ReactJS. Успішної вам трудового тижня, панове!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.