Що таке шорт і лонг та як їх використовувати у торгівлі криптовалютами?
Головне
- Шорти та лонги – короткі та довгі позиції (на продаж та на покупку) у трейдингу . Застосовуються головним чином під час маржинальної торгівлі, тобто торгівлі з плечем.
- Більшість криптовалютних активів характерна висока волатильність. Використання шортів та лонгів дає можливість трейдерам отримувати прибуток у процесі цінових коливань.
- При торгівлі в довгих і коротких позицій слід пам’ятати про хеджування — певні дії, спрямовані на захист від ситуацій, коли ринок рухається у протилежному напрямку відкритим позиціям.
Походження шортів та лонгів
У середньовічній Європі для обліку боргів використовувалися ціпки-бирки або лічильні палиці, що виготовляються з ліщини. На одній із граней бірки поперечними насічками позначали суму, що пускається в оборот, після чого розбирали бірку вздовж через насічки, але не повністю, а з відрубом в районі «рукоятки». В результаті виходила довга частина з рукояткою (stock) та коротка частина (foil), що доповнює цю довгу частину до повної палички. Насічки були на обох частинах. За збігом цих частин проводився контроль. Вважалося, що через фактуру ліщини підробка була неможлива. Дві частини зберігали дві сторони-учасниці транзакції. Із цієї практики, ймовірно, виникли терміни «фондовий ринок» (stock market), а також «лонг» (long) і «шорт» (short).
Висловлювання «короткі» і «довгі» позиції набули поширення на американських фондових і товарно-сировинних біржах 1850-ті роки. Можливо, найраніша згадка про короткі і довгі позиції присутня в журналі The Merchant’s Magazine, and Commercial Review, Vol. XXVI, за січень-червень 1852 року.
Незважаючи на назви, період для короткої позиції може бути досить довгим (тиждень, місяць), а період для лонга досить коротким. Зі світу традиційних фінансів терміни шорт і лонг перекочували в біткоін-індустрію.
Хто такі «бики» та «ведмеді»
Біржових гравців прийнято називати биками чи ведмедями залежно від того, якої стратегії вони йдуть. Тих, хто грає на підвищення (тобто тих, хто відкриває лонги), називають «биками», а гравців, які розміщують короткі позиції, тобто ставлять на зниження ринку — «ведмедями».
Ці терміни умовні: на крипторинці немає чистих бугаїв і ведмедів, часто один і той же трейдер одночасно торгує і в шорт, і в лонг, хоча обсяги позицій можуть відрізнятися.
Що таке лонг
Лонг (довга позиція) – купівля активу в очікуванні того, що він зросте в ціні. Розмір прибутку залежить від збільшення вартості активу. Довга позиція є найбільш популярним типом угоди у роздрібних інвесторів та використовуються на спотовому ринку.
Що таке шорт
Шорт простими словами – продаж фінансового інструменту в очікуванні, що він подешевшає.
Однак механіка короткої позиції дещо складніша за лонг. У рамках цієї схеми трейдер бере актив у борг і продає його на відкритому ринку за поточною ціною. Потім він чекає падіння курсу, купує ту кількість активу, яку брав у борг, за нижчим курсом і віддає борг із відсотками. Отриманий завдяки змінам цін прибуток трейдер залишає собі. У протилежному випадку, якщо ціна активу підвищиться, інвестор отримає збитки.
Приклад
У грудні 2017 року трейдер придбав біткоїни по $19 000 за монету. Він продав ці монети в той же період за $19 000, а потім виплатив позикодавцю приблизно $6000 за кожен BTC, коли в лютому 2018 року ціна значно знизилася . З кожної монети він отримав прибуток у $13 000.
До чого тут маржинальна торгівля
Якщо на спотовому ринку криптовалют можна, по суті, торгувати лише довгими позиціями (хоча і є прийоми, за логікою схожі на шортинг), то в маржинальній торгівлі стає можливим повноцінне відкриття коротких.
У рамках маржинальної торгівлі, яка дає можливість здійснювати угоди з плечем, користувач повинен надати заставу — внести на депозит суму (маржу), яка гарантує виплату боргових зобов’язань за встановленими біржею правилами.
Концепція маржі тісно пов’язана з концепцією левериджу або кредитного плеча (leverage) – множника, який збільшує доступний для операції депозит користувача за рахунок позикових коштів. На ринку криптовалют цей коефіцієнт може коливатися від 2:1 до 100:1 та більше. Тобто торгівля із плечем 50x означає, що при внесенні на депозит готівки на суму $100 ви можете відкрити позиції на суму до $5000.
Якщо ринкова вартість криптовалюти рухається в бік, що очікується трейдером, дохід збільшується пропорційно обраному кредитному плечу. У момент закриття такої позиції тіло застави повертається кредитору разом із комісійними зборами, а залишок отриманого прибутку зараховується на рахунок користувача.
Якщо ж ціна рухається у протилежному напрямку, то, як тільки вартість активів (і власних, і позикових) трейдера досягає розміру кредиту з відсотками (суми, яку трейдер має повернути кредитору), біржа автоматично ліквідує всі позиції гравця та повертає кредитору його кошти. У суму, яку кредитор повертає, повністю входить маржа.
У класичній торгівлі із плечем на фондовому ринку ліквідації позиції передує так званий маржин-кол — вимога додаткового забезпечення. Часто маржин-коллом називають безпосередньо момент ліквідації, на сленгу криптотрейдерів – “зловити моржа”.
Невдалу угоду трейдер може завершити самостійно, не чекаючи на ліквідацію. При цьому він втрачає не всю позицію, а лише частину маржі. Самостійно ліквідувати позицію можна вручну і за допомогою “стоп-лосса” (Stop Loss) – ордера для обмеження торгових ризиків, що передбачає автоматичне закриття угоди при досягненні певної цінової позначки.
Що таке хеджування?
На криптовалютному ринку застосовується механізм, відомий як хеджування — страхування на випадок, якщо тренд руху ціни активу не відповідає позиції трейдера. Наприклад, у вас відкрита довга позиція, а ціна криптовалюти знижується.
В основі хеджування – відкриття шорт-позицій, які врівноважують лонг-позиції та дозволяють залишитися «в нулі» при небажаній зміні ринкової ситуації. Інвестор залишає початкову лонг-позицію незайманою і відкриває шорт або ж використовує додаткові можливості.
Хеджування позиції — рішення для середньо- та довгострокової стратегії. Цей механізм дещо суперечить внутрішньоденному трейдингу, де переважають ринкові спекуляції. Популярний спосіб хеджування позицій передбачає використання ф’ючерсних контрактів: безстрокових та термінових.
Безстрокові контракти працюють за таким принципом: щовісім годин встановлюється так звана ставка фінансування. Останню учасники угод платять один одному замість того, щоб переказувати самі контракти або їх повні вартості. Залежно від ринкової ситуації платять ставку або власники лонг-контрактів власникам шортів, або навпаки.
Термінові контракти виконуються автоматично, якщо інвестор не закриває їх до дня експірації. Хеджуватися можна не лише ф’ючерсами, а й опціонами — похідними фінансовими інструментами для більш розвинених учасників ринку.
Що таке усереднення?
У рамках цієї стратегії інвестор скуповує актив за дедалі нижчою ціною, знижуючи тим самим середню вартість покупки.
Приклад
Ціна біткоїну досягла $29000, потім почала знижуватися. Побачивши фазу корекції, трейдер став купувати монети на послідовних рівнях зниження: $28000, $26000, $24000, $22000, $20000. Середня ціна покупки склала $24000. Після фази корекції курс почав зростати і згодом повернувся до рівня $29000 доларів.
Плюси та мінуси лонгів та шортів
Відкриття довгих позицій — зрозуміліша новачкові стратегія, яка зводиться до простого принципу «купуй дешевше, продавай дорожче».
Шортинг може бути ефективною інвестиційною стратегією, але набагато ризикованіший, ніж вкладення на тривалий термін або усереднення. Відкривати короткі позиції великі суми варто лише досвідченим трейдерам, здатним комплексно аналізувати ринкову динаміку.
Спробувати себе у криптотрейдінгу можна на криптобіржі Binance. На цей час це сама велика криптобіржа с великим вибором інструментів для торгівлі.
Всім профіту та будьте обережні при інвестуванні в крипту.
Крапка з комою в JavaScript: Чи дійсно вона вам потрібна?
У JavaScript крапки з комою є необов’язковими.
// Both statements work the same way console.log("Hello") console.log("Hello");
Однак є ситуації, в яких пропуск крапки з комою може призвести до небажаних наслідків. Тому немає однозначної відповіді на питання, чи слід використовувати крапку з комою, чи ні.
Використання крапок з комою завжди викликає суперечки у спільноті JavaScript. Існують вагомі аргументи на користь використання крапки з комою. Але також є вагомі причини, чому їх не слід застосовувати.
Це вичерпний посібник з використання крапок з комою в JavaScript.
Спочатку ми розглянемо правила використання крапок з комою у коді JavaScript. Потім ви дізнаєтеся, як працює автоматична вставка крапки з комою за кадром. І останнє, але не менш важливе: ви побачите список плюсів та мінусів використання крапок із комою.
Наприкінці цього посібника ви зможете вирішити, чи хочете ви використовувати крапки з комою чи ні.
Посібник з використання крапок з комою в JavaScript
Перш ніж обговорювати плюси та мінуси використання крапок із комою, необхідно зрозуміти, як вони взагалі використовуються.
Необхідне використання: Розділити два оператори в одному рядку
Якщо у вас є два оператори JavaScript в одному рядку, ви повинні поділити їх крапкою з комою. Можливо, найпоширенішим прикладом цього є цикл for.
Наприклад:
const numbers = [1, 2, 3, 4, 5]; for (let i = 0; i < numbers.length; i++) { console.log(numbers[i]); }
На виході:
1 2 3 4 5
Цикл for
не буде працювати без крапки з комою, якщо його умова задається в одному рядку.
Необов’язкове використання: Крапки з комою як роздільники операторів
Крім поділу операторів для одного рядка, JavaScript немає інших обов’язкових випадків використання крапки з комою. Однак, за бажанням, ви можете використовувати крапки з комою для завершення оператора, навіть якщо були розриви рядків.
Ось кілька поширених прикладів операторів, які можна завершити крапкою з комою:
let i; // variable declaration i = 5; // value assignment let x = 9; // declaration and assignment var fun = function() {...}; // function definition alert("hi"); // function call
Пам’ятайте, що всі вищезгадані крапки з комою необов’язкові. Код працюватиме і без них.
Уникайте крапок із комою
Є ситуації, у яких слід уникати використання крапок із комою.
Уникайте крапок з комою після '}'
. Не ставте крапку з комою після закриття фігурної дужки }
.
Єдиним винятком є оператор присвоєння, наприклад, такий:
var data = {name: "Alice", age: 25};
У цьому випадку можна використовувати крапку з комою.
Ось кілька прикладів того, як не використовувати крапку з комою після фігурної дужки, що закриває:
if (...) {...} else {...} for (...) {...} while (...) {...} function (arg) { /* actions */ }
Уникайте крапок з комою після )
в операторах if
, for
, while
або switch
.
У попередньому розділі ви дізналися, що не слід використовувати крапку з комою після закриття фігурної дужки. Однак якщо ви випадково це зробите, це буде просто проігноровано.
Жодної шкоди від цього не станеться. Але якщо ви поставите крапку з комою там, де її не повинно бути, то виникнуть проблеми.
Не додавайте крапку з комою після закриває дужки )
в:
- операторів
If
- циклах
For
- циклах
While
- операторах
Switch
Давайте розглянемо приклад того, чому важливо пам’ятати.
Якщо ви напишете оператор if наступним чином:
if (0 > 1); { console.log("Hello") }
Це еквівалентно наступному:
if (0 < 1); console.log("Hello")
У цьому випадку він виводить повідомлення на консоль, хоча явно не повинен цього робити. Це тому, що крапка з комою повністю завершує оператор if
. Потім блок коду, що йде за оператором if
, виконується як окремий. Тому будьте обережні та не зловживайте крапкою з комою!
Винятки при використанні крапки з комою
Раніше у цій статті ви бачили приклад циклу for з крапкою з комою. Це винятковий випадок використання крапки з комою.
Погляньте на цей простий цикл:
for (let i = 0; i < 10 ; i++) { } // Works
Як ви можете бачити, крапка з комою не ставиться відразу після i++ .
Насправді після третього оператора в циклі for не можна ставити крапку з комою.
Якщо ви так зробите, то виникне синтаксична помилка:
for (let i = 0; i < 10 ; i++;) { } // SyntaxError
Це все, що вам потрібно знати, коли йдеться про правила використання крапок з комою в JavaScript.
Тепер давайте коротко обговоримо, чому використання крапок з комою в JavaScript необов’язкове.
Автоматична вставка крапки з комою у JavaScript
JavaScript не вимагає крапок з комою (за винятком одного виключення, яке ви бачили раніше).
Це відбувається тому, що JavaScript досить розумний і може автоматично додавати крапки з комою там, де потрібно.
Все відбувається “за лаштунками”, і ви нічого не помітите.
Такий процес називається автоматичною вставкою крапок з комою ( Automatic Semicolon Insertion . ASI).
Правила ASI у JavaScript
Парсер JavaScript додає крапку з комою в будь-якому з наступних випадків:
- Наступний рядок коду починається з коду, який явно перериває поточний рядок коду.
- Коли наступний рядок коду починається з
}
. - Досягши кінця файлу.
- Якщо будь-який з наступних операторів зустрічається у вигляді окремого рядка
return
(повернення)break
(перервати)throw
(викинути [помилку])continue
(продовжити)
Важливо розуміти, що ASI не завжди є коректним на 100%.
Крапка з комою використовується для поділу операторів на JavaScript, а не для їх завершення.
Це те, що ASI намагається зробити вас.
Якщо говорити простіше, то правила ASI можна сформулювати так:
Не кожне перенесення рядка вимагає крапки з комою. Однак розрив рядка, який не піддається парсингу без крапки з комою, потребує її використання.
Наприклад:
let x x = 10 console.log(x)
Цей фрагмент коду інтерпретується ASI як:
let x; x = 10; console.log(x);
В даному випадку ASI проробив відмінну роботу, зумівши розібратися в тому, як триває код між рядками 2-4.
Однак, іноді він може не знати, чого ми намагаємося досягти.
Наприклад, цей рядок коду призводить до помилки
const s = 'World' const ab = "Hello" + s [3].forEach(n => console.log(n))
В результаті виникає така помилка:
Uncaught TypeError: s[3].forEach is not a function at :4:5
За описом помилки ви можете здогадатися, чому це відбувається.
Причина, через яку цей валідний фрагмент коду не працює, полягає в тому, що ASI не вставляє крапку з комою після другого рядка.
Натомість, він інтерпретує рядки 2 і 4 як продовження одного і того ж оператора наступним чином (відповідно до правила ASI номер 1):
const s = 'World'; const ab = "Hello" + s[3].forEach(n => console.log(n));
ASI думає, що s
– це масив, і ви намагаєтеся отримати доступ до його 4 елемента за допомогою s
[3] .
Але це не те, що ви плануєте здійснити.
Щоб змусити цей рядок працювати так, як очікується, необхідно вручну додати крапку з комою наприкінці другого рядка:
const s = 'World' const ab = "Hello" + s; [3].forEach(n => console.log(n)) // Prints '3'
Тепер код працює так, як передбачалося.
Інший приклад, коли ASI може викликати проблеми, – це оператори return
.
Наприклад:
function getData() { return { name: 'Bob' } } console.log(getData())
На виході:
undefined
В результаті виводиться undefined
, хоча малося на увазі, що з’явиться ім’я {name: 'Bob'}
.
Так відбувається тому, що 4 правило ASI говорить, якщо оператор return
зустрівся у вигляді окремого рядка, то ставиться крапка з комою.
Тому ASI бачить наведений вище код так:
function getData() { return; { name: 'Bob' } } console.log(getData())
Іншими словами, функція getData()
нічого не повертає, а потім випадково створює об’єкт, з яким нічого не робить.
Таким чином, в консолі ви бачите undefined
.
Для виправлення цього потрібно додати фігурну дужку, що відкриває, в той же рядок, що і оператор return
:
function getData() { return { name: 'Bob' } } console.log(getData())
На виході:
{ name: "Bob" }
Тепер цей фрагмент коду працює як належить.
Завдяки цьому розділу ви навчилися бути обережними з ASI. Незважаючи на те, що в більшості випадків він діє правильно, іноді його інтерпретація ваших намірів може виявитися неправильною.
Далі перейдемо до найцікавішого, тобто до причин, з яких ви повинні або не повинні використовувати крапку з комою JavaScript.
Чому ви повинні використовувати крапку з комою: 5 причин
Використання або невикористання крапок із комою викликає спекотні суперечки серед веб-розробників.
Ось 5 причин, з яких ви повинні використовувати крапку з комою у своєму коді.
1. Іноді обов’язкова
Як було сказано раніше у цій статті, іноді необхідно використовувати крапку з комою.
Наприклад, якщо ви пишете цикл for
, необхідно використовувати крапку з комою при вказівці параметра циклу та умов. В іншому випадку цикл не працюватиме.
Крім того, ASI (автоматична вставка крапки з комою) JavaScript не завжди відповідний на 100%.
Іноді він може неправильно витлумачити ваші наміри і не додати крапку з комою там, де вона потрібна. Це може призвести до появи непередбачених помилок у коді.
Один із таких прикладів ви також бачили раніше у цьому посібнику.
2. Ви звикли використовувати крапки з комою
Можливо, у процесі роботи ви звикли до використання крапок із комою в коді.
У деяких інших мовах широко використовуються крапки з комою, тому звикання до них є звичайною справою. Якщо ваш мозок не сприймає код JavaScript без крапок із комою, навіщо від них відмовлятися?
Не соромтеся використовувати крапки з комою, щоб зробити код більш зрозумілим для вас, якщо це те, що ви звикли робити.
3. Явно вказує на закінчення оператора
Крапка з комою – це простий спосіб чітко позначити закінчення оператора. При використанні крапки з комою немає місця для плутанини. Рядок коду закінчується на крапці з комою.
4. Менше приводів для занепокоєння
Якщо ви завжди використовуєте крапку з комою, то не варто переживати з приводу ASI. Це дає вам менше приводів для занепокоєння.
Після кожного рядка коду вам не потрібно замислюватися про те, чи зіпсує відсутність крапки з комою ситуацію чи ні. Однак ASI все одно може зіпсувати все, як ви бачили на прикладі оператора return .
5. ASI може бути змінено
Правила ASI можуть змінитися у майбутньому. Хоча це малоймовірно, але таке можливо. Таким чином, покладатися на правила ASI про вставку крапок з комою завжди за одним і тим же принципом надійно не на 100%.
Якщо ви пишете код з урахуванням поточного ASI, можете зіткнутися з деякими проблемами, якщо правила поміняються. Але майте на увазі, що у 99,9% випадків ASI виконує свою роботу коректно. Більше того, правила навряд чи зміняться найближчим часом.
Тепер, коли ви побачили безліч причин для використання крапок з комою, поговоримо про те, чому їх не слід використовувати.
Чому не слід використовувати крапки з комою: 3 причини
Зверніть увагу, що якщо ви чуєте, як хтось каже: “Ніколи не слід використовувати крапку з комою”, він помиляється. Це тому, що крапка з комою в окремих випадках обов’язкова.
У будь-якому випадку, поговоримо про мінуси крапок з комою, перерахувавши 3 причини, з яких їх не слід використовувати.
1. Крапки з комою вставляються автоматично
Як ви вже з’ясували, крапки з комою вставляються ASI. Таким чином, вам не потрібно писати те, що все одно буде проігноровано.
2. Менше написаного коду та менше шуму
Кожен символ коду впливає на читабельність та якість коду. Якщо ви не використовуєте крапки з комою, то цим заощадите символи в кожному написаному рядку коду.
3. Кілька операторів в одному рядку – погана практика
Використання крапок із комою дозволяє записувати по кілька операторів на одному рядку. Але це погана практика.
Ви ніколи не повинні писати оператори в одному рядку (якщо це не потрібно).
При використанні крапок з комою виникає ймовірність того, що у вас сформується ця погана звичка. Якщо ви не використовуєте крапки з комою, то можливості писати оператори в одному рядку у вас не буде.
Так використовувати крапки з комою чи ні?
Під час вивчення цієї статті ми обговорили причини, через які варто і не слід використовувати крапку з комою.
Як показує практика, є набагато більше причин для використання капок з комою, ніж для її відсутності. Таким чином, я рекомендую використовувати крапки з комою. Проте рішення лишається за вами.
Якщо ви працюєте в команді розробників програмного забезпечення, ви повинні дотримуватися загальноприйнятих правил. Якщо команда використовує крапки з комою, то і ви повинні їх застосовувати. Якщо команда цього не робить, то вам не слід їх ставити.
Також пам’ятайте, що потрібно бути послідовним у застосуванні крапок з комою та без них.
Якщо ви пропустили одну крапку з комою, то пропускайте їх усі (крім обов’язкових). Ви також можете налаштувати свій лінтер на автоматичне видалення крапок з комою.
Висновок
Сьогодні ви дізналися про використання крапок з комою у JavaScript. Нагадаємо, що крапки з комою не є обов’язковими у JavaScript. Водночас процес автоматичної вставки крапки з комою (ASI) додає крапки з комою там, де це необхідно.
Однак ASI не є правильним у 100% випадків. Крім того, у деяких ситуаціях ви просто зобов’язані використовувати крапку з комою. Інакше код не працюватиме.
Використовувати крапки з комою чи ні – повністю залежить від вас. На мій погляд, користі від використання крапок з комою більше, ніж від їхньої відсутності. Але ваша думка може відрізнятись.
Переклад статті “JavaScript Semicolon: Do You Really Need It? (Updated 2022)“
React, Vue, Angular. Що краще?
Під час розвитку веб-розробки 3 JavaScript-фреймворку стали добре відомі всім front-end розробникам: React, Vue.js та Angular.
React вважається бібліотекою інтерфейсу користувача, Angular – повномасштабним front-end фреймворком, що надає власні інструменти для всіх пов’язаних з розробкою веб-додатків функцій, а Vue – прогресивним фреймворком, реалізованим як додаткова розмітка для HTML.
Всі три фреймворки можуть використовуватися практично взаємозамінно для створення компонентних frontend-додатків з розширеними можливостями інтерфейсу користувача. Однак остаточний вибір залежить від вимог проекту та переваг розробника.
Кожен фреймворк має різну архітектуру, продуктивність у різних сценаріях, екосистему та інструменти, які ми намагатимемося розглянути у цій статті, щоб краще зрозуміти їх зручність використання.
Архітектура
1. React
Як видно з офіційного прикладу Hello World нижче, React не вимагає певної структури проекту, і ви можете почати використовувати його всього з декількох рядків коду.
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') );
React-елементи є найбільш базовими складовими React-додатків. Оскільки React DOM забезпечує їхнє ефективне оновлення при кожній зміні, вони є більш потужними, ніж стандартні елементи DOM.
Більші будівельні блоки, відомі як компоненти, визначають незалежні складові, що багаторазово використовуються, які використовуються у всьому додатку. Вони приймають вхідні дані, відомі як пропи, та створюють елементи, які згодом представлені користувачеві. Найбільш поширений варіант структурування проекту полягає у розбитті інтерфейсу на такі компоненти як імпорт в основний компонент App.js та його наступний рендер у React DOM.
React побудований на JavaScript, але також широко використовується JSX (JavaScript XML), розширення граматики, що дозволяє створювати елементи, що одночасно містять JavaScript і HTML. React JavaScript API та блоки, написані за допомогою JSX, сумісні, але здебільшого JSX більш зручний для використання та дозволяє уникнути написання довгого та, можливо, неінтуїтивного створення HTML елементів за допомогою JavaScript. Для порівняння нижче представлений той самий компонент написаний за допомогою JSX:
const Hello = (props) => { return <div>Hello {props.toWhat}</div> ; } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<Hello toWhat="World" />);
та React JavaScript API:
const Hello = (props) => { return React.createElement('div', null, `Hello ${props.toWhat}`); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render React.createElement(Hello, {toWhat: 'World'}, null));
React також підтримує TypeScript, але, на щастя менш досвідчених розробників, його використання є опціональним.
2. Vue
Основна бібліотека Vue.js зосереджена лише на шарі View. Її називають прогресивним фреймворком, тому що ми можемо розширити її функціональність за допомогою офіційних та сторонніх бібліотек, таких як Vue Router або Vuex, щоб перетворити її на справжній фреймворк.
Хоча Vue не пов’язаний із патерном MVVM (Model-View-ViewModel), його дизайн був частково натхненний ним. У Vue ви працюватимете в основному на рівні ViewModel, щоб переконатися, що дані програми обробляються таким чином, щоб фреймворк міг відобразити актуальний вид і стан програми за мінімальну кількість ре-рендерів.
Синтаксис шаблонів Vue дозволяє створювати компоненти, поєднуючи звичний HTML зі спеціальними директивами та можливостями. Цей синтаксис шаблонів є кращим, хоча чистий JavaScript та JSX також підтримуються. Компоненти Vue невеликі, самодостатні і можуть бути повторно використані у всьому додатку. Унікальною деталлю Vue є так звані Однофайлові компоненти (SFC) з розширенням .vue, які складаються з трьох частин – template, script та style , значення яких інтуїтивно зрозуміле кожному розробнику.
Типовий формат .vue файлу наведений нижче:
<template> ... </template> <script> ... </script> <style> ... </style>
Template – написаний на розширеній версії HTML, він є директивою для фреймворку у тому, як проводити остаточну розмітку компонента з урахуванням його внутрішнього стану. Дозволяє створювати розмітку щодо умов або динамічно за допомогою vue-директив (v-if, v-for та ін.).
Script – призначений для написання логіки компонента та контролю його стану. Vue як і React дозволяє опціонально використовувати JavaScript, і TypeScript.
Style – вміщує CSS (так підтримує написання стилів на CSS пре-процессорах). Написані стилі енкапсулируются в компоненті не впливають інші компоненти.
Багатьом концепт приміщення всього необхідного коду для функціонування компонента в одному файлі видасться досить зручним. SFC є рекомендованим способом організації коду в Vue.js проектах, особливо великих. Як і у випадку з React, рекомендовано використовувати основний компонент App.vue для рендерування вашої програми.
3. Angular
AngularJS, оригінальний фреймворк, є MVC (Model-View-Controller) фреймворком. Але в Angular 2 немає суворого зв’язку з MV*-патернами, оскільки він також ґрунтується на компонентах.
Проекти в Angular структуровані на Модулі, Компоненти та Сервіси. Кожна програма Angular має як мінімум один рутовий компонент і один рутовий модуль.
Angular модулі – це контейнери для цілісного блоку коду, призначеного для домену програми, робочого процесу або тісно пов’язаного набору можливостей. Вони можуть містити компоненти, сервіс-провайдери та інші файли коду, сфера застосування яких визначається модулями, які вони містять. Вони можуть імпортувати функціональність, що експортується з інших модулів, або навпаки.
Кожен компонент в Angular містить шаблон, логіку з метаданими та опціонально стилі, розділені на окремі файли на відміну від Vue. Метадані для компонента вказують Angular, де знайти будівельні блоки, необхідні створення і уявлення виду компонента. Шаблони Angular написані на HTML, але також можуть включати синтаксис шаблонів Angular зі спеціальними директивами, як і у випадку з Vue.
Сервіси Angular використовуються компонентами для делегування завдань, таких як отримання даних або перевірка введення. Вони є окремою частиною програм Angular, на відміну від React та Vue, яким потрібно встановлювати додаткові бібліотеки для досягнення подібних цілей. Хоча Angular не змушує їх використання, настійно рекомендується структурувати додатки як набір окремих сервісів, які можна використовувати повторно.
Angular побудований на TypeScript, тому рекомендується використовувати його, хоча звичайний JavaScript також підтримується.
Екосистема
Ви можете заощадити багато часу при розробці програм, використовуючи Open Source ПЗ. Оскільки вони пройшли через численні вдосконалення і були використані в багатьох проектах, вони зазвичай перевершують кастомно розроблені компоненти. Дуже важливо враховувати доступність попередньо створених елементів, тем та інших інструментів, які можуть спростити створення вашої програми.
1. React
Глобальне керування станом часто використовується у зовнішніх програмах для зберігання таких даних, як інформація про користувача, токени і т.д. Redux – найпопулярніший проект управління глобальним станом JavaScript. Більшість React-розробників використовують офіційний React-біндинг для Redux, який підтримує команда проекту.
Оскільки React дуже популярний, за допомогою простого пошуку в Гуглі або на Гітхабі дуже легко знаходити готові компоненти та пекеджі практично на будь-який смак та необхідність.
Екосистема React також включає React Native, що дозволяє створювати нативні програми для iOS та Android написані на React. Таким чином, React може стати чудовим вибором для створення мобільних програм з використанням веб-технологій.
React є частиною стека MERN, до якого входять MongoDB, ExpressJS, React та NodeJS. Перевагою даного стеку є єдина мова програмування Javascript.
2. Vue
Хоча Redux може бути використаний з Vue, проте офіційного біндингу, як у випадку з React, немає. Але не варто переживати, оскільки існує Vuex – офіційний аналог Redux, створений спеціально для програм Vue і підтримується командою розробки Vue.js.
У перші дні існування Vue було складніше знайти готові до використання компоненти. Але з того часу, як спільнота зросла, з’явився широкий вибір компонентів та бібліотек, які можуть бути використані для прискорення розробки.
Для розробки мобільних програм існує перспективний проект під назвою Weex, розроблений компанією Alibaba. Однак Weex далеко не такий зрілий та потужний, як React Native. Більше того, оскільки проект розробляється та використовується більше в Китаї, складніше знайти документацію та вирішення проблем англійською мовою.
Vue часто використовується з Laravel завдяки їхній гарній інтеграції. Laravel пропонує повну JavaScript та CSS підтримку, що дозволяє використовувати Vue у Laravel проектах.
3. Angular
Для управління станами в Angular також є офіційний проект NgRx, натхненний Redux.
Як і у випадку з Vue і React, існує безліч готових до використання компонентів, які легко імпортуються в Angular проекти. Однак варто пам’ятати про наявність багатьох офіційних компонентів у бібліотеці Angular Material. Це офіційний проект від Google, який пропонує готові компоненти (кнопки, списки, діалогові вікна тощо) для програм Angular.
NativeScript є оптимальним варіантом для створення кросплатформових мобільних додатків у Angular. Він також може бути використаний з Vue, але підтримка Angular більш розвинена.
Angular є частиною відомого стека MEAN, що складається також із MongoDB, ExpressJS та NodeJS. Подібно до стеку MERN, він повністю покладається на JavaScript як для фронтенду, так і для бекенда.
Продуктивність
Продуктивність фреймворку чи бібліотеки – ще один фактор, який потрібно враховувати. Продуктивність часто не має значення, особливо якщо ви працюєте над невеликим проектом. Проте продуктивність ставатиме проблемою у міру збільшення масштабу та складності проекту.
Однак варто пам’ятати, що слідувати кращим практикам розробки і стежити за якістю коду часто більш важливо, ніж вибір фреймворку для кращої продуктивності програми. Тим не менш, розглянемо деякі показники продуктивності.
1. Бенчмарк JS фреймворків
Проект JS Framework Benchmark є гарним способом переглянути порівняння продуктивності різних фреймворків, за допомогою виконання базових операцій над таблицею з 1000 рандомізованих записів.
React і Angular справляються значно гірше за Vue зі свапом рядків і по суті це єдині суттєві відмінності в бенчмарках рендерингу таблиці – здебільшого вони не дадуть сильно помітних результатів. Єдине, можна сказати, що операція вибору рядків у таблиці є досить поширеною, що і ставить React в ледь помітне програшне становище.
Також React і Vue демонструють високі показники використання пам’яті та швидкості ініціалізації, проте Angular вимагає для цього більше часу. Базовий скрипт запускається за 150-200 мілісекунд, і Angular більш вимогливий до пам’яті найчастіше через те, що це повноцінний фреймворк із функціоналом, для якого React або Vue проекти зазвичай встановлюють сторонні бібліотеки за потребою.
2. Дослідження продуктивності Perf Track
Проект Perf Track від Google Chrome Labs() ставить за мету перевірити продуктивність вебсайтів, написаних на популярних фреймворках. Давайте подивимося на дані нижче:
React метрика
Vue метрика
Angular метрика
Варто зауважити, що наведені дані були зібрані на момент 1 листопада 2020 року для мобільних пристроїв і на них впливає не тільки вибір фреймворку, але і безліч інших факторів. Для третього пункту, непередбаченого зсуву лейауту сторінки при навантаженні елементів, вибір фрейворку зовсім мало впливає. Однак, спробуємо зробити деякі висновки.
Перше промальовування контенту та найбільше промальовування контенту показує, що Vue та React краще справляються з провантаженням і рендерингом сторінки, ніж Angular, якому зазвичай потрібно більше часу, щоб підготувати програму. Затримкою першого введення (3 пункт) є тимчасовий проміжок між процесом користувача (клік на кнопку, введення даних) і реакцією сторінки нею і, на щастя, все 3 фреймворка показують винятково позитивні результати за цим параметром. Також варто зауважити, що понад 70% додатків на Vue завантажують менше 1MB JavaScript для своєї роботи, тоді як інші 2 фреймворки та Angular зокрема зазвичай займають набагато більше пам’яті. Однак, потрібно розуміти, що це може означати, що більшість маленьких проектів написані на Vue, тоді як Angular використовується для більш потужних проектів.
3. Додаткові прийоми покращення продуктивності
Основними двома техніками, що покращують роботу фронтенд додатків, є SSR (server-side rendering) та віртуалізація. Рендеринг за сервера насправді є здатність докладання скомпілювати HTML-файли з сервера на повністю провантажену сторінку для користувача, а віртуалізацією є навантаження компонентів у міру їх вимоги (наприклад у міру скролінгу сторінки).
React має за замовчуванням офіційний пекедж ReactDOMServer для рендерингу на стороні сервера, а для віртуалізації багато хто використовує сторонні бібліотеки React-Virtualized та React-Window
Vue також за замовчуванням має SSR пекедж Server-Renderer, проте з віртуалізацією потенційні розробники можуть мати проблеми, оскільки навіть найпопулярніша бібліотека Vue Virtual Scroll List має кілька багів і не настільки стабільна, як її аналоги для інших фреймворків.
Angular вкотре підтверджує своє звання повноцінного фреймворку, маючи офіційний Angular Universal для серверного рендерингу та вбудовані компоненти для віртуалізації.
Складність навчання та популярність
Важливою складовою при виборі фреймворку для девелоперів, які не мають попереднього досвіду, є концепти, які кожен привносить фреймворк, а також активність спільноти.
1. React
На перший погляд може здатися, що React – найпростіший у використанні фреймворк, що просто імпортуємо бібліотеку, і можна писати JavaScript з використанням React API. Однак на самому початку ми вже розглянули, наскільки незручно виглядає простий Hello world! Приклад, написаний на чистому JavaScript, тому кожен початківець React девелопер повинен змиритися з фактом, що альтернативи навчанню JSX немає, оскільки його використання є аксіомою у суспільстві для створення HTML-лейауту компонентам. Спочатку необхідність частково переходити на «мікс» з JavaScript та HTML може здатися дещо неінтуїтивною. З іншого боку, починаючи з версії 16.8 React вводить функціональні компоненти,
const exampleComponent = (props) => { ... // JavaScript return( ... // JSX ); }; export default exampleComponent;
Також варто зауважити, що версія 17.0 привнесла можливість часткового апгрейду програми, що дозволяє зберегти функціонал, що покладається на застарілі концепти, і робить React добрим вибором для довгострокової перспективи.
React є найчастіше завантажуваним фреймворком зі статистики npm, і це означає, що у користувачів не повинно бути проблем з пошуком рішень на можливі проблеми при девелопменті, так само як і активність спільноти дозволяє не тільки успішно шукати, але й ставити свої питання на популярних платформах типу StackOverflow.
2. Vue
Одним із концептів, з яким потрібно познайомитися початківцям Vue розробникам, є розширений HTML синтаксис із директивами. Більшість основних Vue директив інтуїтивно зрозумілі – v-if для рендерингу за умови, v-for для рендерингу в циклі, v-on для біндингу функціоналу до івент листенерів тощо. Наявність лейауту, функціоналу та стилів в одному .vue файлі з інтуїтивним синтаксисом також робить розробку кожного компонента максимально простим і без перескакування між файлами.
З релізом Vue 3 у 2020 році, творці фреймворку вирішили безліч проблем, які мала спільнота з використанням Vue для великих проектів, ввівши можливості для ширшого реюзу функціоналу між компонентами. Також було покращено підтримку таких проектів за допомогою рефакторингу вихідного коду Vue на TypeScript.
Так як Vue є «наймолодшим» фреймворком, розмір спільноти природно менший, ніж у React і Angular, і загальна популярність старої версії Vue 2 в основному серед китайських користувачів також створювала деякі проблеми в обміні знаннями та пошуку відповідей на запитання. Однак за тією самою статистикою npm – Vue є лідером у прирості завантажень за останній рік. Значні поліпшення Vue 3 дозволяють бути впевненими, що Vue скоро може обігнати за популярністю Angular.
3. Angular
Звання повноцінного фреймворку не дається легко, і Angular розробникам доводиться знайомитись з багатьма концептами. Angular очікує, що розробники дотримуватимуться певної структури в написанні коду і постійно використовуватимуть модулі з сервісами, крім компонентів. Як і у випадку з Vue необхідно вивчити додатковий HTML синтаксис, що складається з ng-* директив. І варто пам’ятати, що Angular працює найкраще з TypeScript і у разі вибору цього фреймворку потрібно обов’язково ознайомитися з TypeScript. Також складність вивчення підвищує широке використання RxJS – бібліотеки для реактивного програмування, яка дозволить зручно організувати роботу з подіями та асинхронним кодом і є потужнішою, але водночас складною альтернативою промісам.
Будучи старішим фреймворком, ніж React або Vue, і еволюціонувавши зі свого прототипу Angular.js, Angular може похвалитися величезним співтовариством, і він все ще є популярним вибором фреймворку для великих проектів. Однак у першої версії Angular була досить відома проблема – складність апгрейду проекту на новіші версії, яка згодом була виправлена в Angular 2 і вище. Проте останнім часом безліч проектів вважають за краще використовувати React або Vue, особливо ті, що починають як старт-апи з невеликими командами.
Ми розглянули з вами низку основних аспектів, що розрізняють React, Vue та Angular. Насамкінець хочеться сказати, що всі 3 фреймворки знаходяться в активній розробці і регулярно отримують апдейти, тому в поточних реаліях можна без зайвого занепокоєння використовувати будь-який з них. Неможливо передбачити довгострокову релевантність будь-якого з фреймворків, але важливо помітити, що Angular вже не росте так само швидко, як колись, a Vue навпаки розвивається активніше за інших, переймаючи корисні концепти у React і Angular.
При виборі фреймворку для розробки важливо визначити наявність доступних фахівців, а також тимчасові ресурси, необхідні для навчання нових. Досвідченість команди може стати вирішальним чинником. І нарешті, сам проект, його комплексність, розмір та напрямок також може вплинути на ваше рішення.
Переклад статті “React vs Vue vs Angular“
Redux Toolkit як засіб ефективної розробки
В даний час розробка левової частки веб-застосунків, заснованих на фреймворку React, ведеться з використанням бібліотеки Redux. Ця бібліотека є найпопулярнішою реалізацією FLUX-архітектури і, незважаючи на низку очевидних переваг, має дуже суттєві недоліки, такі як:
- складність і “багатослівність” рекомендованих патернів для написання та організації коду, що тягне за собою велику кількість бойлерплейту;
- відсутність вбудованих засобів управління асинхронною поведінкою та побічними ефектами, що призводить до необхідності вибору відповідного інструменту з безлічі аддонів, написаних сторонніми розробниками.
Для усунення цих недоліків розробники Redux представили бібліотеку Redux Toolkit. Цей інструмент є набір практичних рішень та методів, призначених для спрощення розробки додатків з використанням Redux. Розробники цієї бібліотеки мали на меті спростити типові випадки використання Redux. Цей інструмент не є універсальним рішенням у кожному з можливих випадків використання Redux, але дозволяє спростити код, який потрібно написати розробнику.
У цій статті ми розповімо про основні інструменти, що входять до Redux Toolkit, а також, на прикладі фрагмента нашої внутрішньої програми, покажемо, як їх використовувати у коді, що вже є.
Коротко про бібліотеку
Коротка інформація про Redux Toolkit:
- до релізу бібліотека називалася redux-starter-kit;
- реліз відбувся наприкінці жовтня 2019 року;
- Бібліотека офіційно підтримується розробниками Redux.
Згідно з заявою розробників Redux Toolkit виконує такі функції:
- допомагає швидко розпочати використання Redux;
- спрощує роботу з типовими завданнями та кодом Redux;
- дозволяє використовувати найкращі практики Redux за замовчуванням;
- пропонує рішення, які зменшують недовіру до бойлерплейтів.
Redux Toolkit надає набір як спеціально розроблених, так і додає ряд інструментів, що добре себе зарекомендували, які зазвичай використовуються спільно з Redux. Такий підхід дозволяє розробнику вирішити, як і які інструменти використовувати у своєму додатку. Під час цієї статті ми будемо відзначати які запозичення використовує дана бібліотека. Більш повну інформацію та залежності Redux Toolkit можна отримати з опису пакету @reduxjs/toolkit.
Найбільш значущими функціями, які надає бібліотека Redux Toolkit є:
configureStore
– функція, призначена спростити процес створення та налаштування сховища;createReducer
— функція, що допомагає лаконічно та зрозуміло описати та створити ред’юсер;createAction
– повертає функцію творця дії для заданого рядка типу дії;createSlice
– поєднує в собі функціоналcreateAction
іcreateReducer
;createSelector
– функція з бібліотеки Reselect, переекспортована для простоти використання.
Також варто відзначити, що Redux Toolkit повністю інтегрований з TypeScript. Докладнішу інформацію про це можна отримати з розділу Usage With TypeScript офіційної документації.
Застосування
Розглянемо використання бібліотеки Redux Toolkit на прикладі фрагмента програми, що реально використовується React Redux.
Примітка. Далі у статті наводиться вихідний код як без використання Redux Toolkit, так і з використанням, що дозволить краще оцінити позитивні та негативні сторони використання цієї бібліотеки.
Завдання
В одному з наших внутрішніх додатків виникла потреба додавати, редагувати і відображати інформацію про релізи програмних продуктів, які ми випускаємо. Для кожної з цих дій були розроблені окремі функції API, результати виконання яких потрібно додавати в Redux store. Як засіб управління асинхронною поведінкою та побічними ефектами будемо використовувати Thunk
.
Створення сховища
Початковий варіант вихідного коду, що здійснює створення сховища, виглядав наступним чином:
import { createStore, applyMiddleware, combineReducers, compose, } from 'redux'; import thunk from 'redux-thunk'; import * as reducers from './reducers'; const ext = window.__REDUX_DEVTOOLS_EXTENSION__; const devtoolMiddleware = ext && process.env.NODE_ENV === 'development' ? ext() : f => f; const store = createStore( combineReducers({ ...reducers, }), compose( applyMiddleware(thunk), devtoolMiddleware ) );
Якщо уважно поглянути на наведений код, можна побачити досить довгу послідовність дій, яку необхідно зробити, щоб сховище було повністю налаштовано. Redux Toolkit містить інструмент, покликаний спростити цю процедуру, а саме: функцію configureStore
.
Функція configureStore
Даний інструмент дозволяє автоматично комбінувати редьюсери, додати мідлвари Redux (за замовчуванням включає redux-thunk
), а також використовувати розширення Redux DevTools. Як вхідні параметри функція configureStore
приймає об’єкт з такими властивостями:
reducer
— набір ред’юсерів користувача,middleware
– опціональний параметр, що задає масив мідлварів, призначених для підключення до сховища,devTools
— параметр логічного типу, що дозволяє увімкнути встановлене у браузер розширення Redux DevTools (значення за промовчанням — true),preloadedState
– опціональний параметр, що задає початковий стан сховища,enhancers
– опціональний параметр, що задає набір підсилювачів.
Для отримання найбільш популярного списку мідлвар можна скористатися спеціальною функцією getDefaultMiddleware
, що також входить до складу Redux Toolkit. Ця функція повертає масив із включеними за замовчуванням до бібліотеки Redux Toolkit мідлварами. Перелік цих мідлвар відрізняється залежно від того, в якому режимі виконується ваш код. У режимі production масив складається тільки з одного елемента – thunk
. У режимі development на момент написання статті список поповнюється такими мідлварами:
serializableStateInvariant
— інструмент, спеціально розроблений для використання в Redux Toolkit і призначений для перевірки дерева станів на наявність несеріалізованих значень, таких як функції, Promise, Symbol та інші значення, що не є простими JS-даними;immutableStateInvariant
– мідлвар з пакету redux-immutable-state-invariant , призначений для виявлення мутацій даних, що містяться в сховищі.
Для завдання списку мідлварів, що повертається, функція getDefaultMidlleware
приймає об’єкт, що визначає перелік включених мідлварів і налаштування для кожного з них. Докладніше з цією інформацією можна ознайомитись у відповідному розділі офіційної документації.
Тепер перепишемо ділянку коду, відповідальний створення сховища, скориставшись описаними вище інструментами. В результаті отримаємо наступне:
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; import * as reducers from './reducers'; const middleware = getDefaultMiddleware({ immutableCheck: false, serializableCheck: false, thunk: true, }); export const store = configureStore({ reducer: { ...reducers }, middleware, devTools: process.env.NODE_ENV !== 'production', });
На прикладі даної ділянки коду добре видно, що функція configureStore
вирішує такі проблеми:
- необхідність комбінувати ред’юсери, автоматично викликаючи
combineReducers
, - необхідність комбінувати мідлвари, автоматично викликаючи
applyMiddleware
.
А також дозволяє зручніше включити розширення Redux DevTools, використовуючи функцію composeWithDevTools
з пакету redux-devtools-extension
. Все сказане вище свідчить про те, що використання цієї функції дозволяє зробити код більш компактним і зрозумілим.
На цьому створення та налаштування сховища завершено. Передаємо його у провайдер і переходимо далі.
Дії, творці дій та редьюсер
Тепер розглянемо можливості Redux Toolkit щодо розробки дій, творців дій і редьюсера. Початковий код без використання Redux Toolkit був організований у вигляді файлів actions.js і reducers.js. Вміст файлу actions.js виглядав так:
import * as productReleasesService from '../../services/productReleases'; export const PRODUCT_RELEASES_FETCHING = 'PRODUCT_RELEASES_FETCHING'; export const PRODUCT_RELEASES_FETCHED = 'PRODUCT_RELEASES_FETCHED'; export const PRODUCT_RELEASES_FETCHING_ERROR = 'PRODUCT_RELEASES_FETCHING_ERROR'; … export const PRODUCT_RELEASE_UPDATING = 'PRODUCT_RELEASE_UPDATING'; export const PRODUCT_RELEASE_UPDATED = 'PRODUCT_RELEASE_UPDATED'; export const PRODUCT_RELEASE_CREATING_UPDATING_ERROR = 'PRODUCT_RELEASE_CREATING_UPDATING_ERROR'; function productReleasesFetching() { return { type: PRODUCT_RELEASES_FETCHING }; } function productReleasesFetched(productReleases) { return { type: PRODUCT_RELEASES_FETCHED, productReleases }; } function productReleasesFetchingError(error) { return { type: PRODUCT_RELEASES_FETCHING_ERROR, error } } … export function fetchProductReleases() { return dispatch => { dispatch(productReleasesFetching()); return productReleasesService.getProductReleases().then( productReleases => dispatch(productReleasesFetched(productReleases)) ).catch(error => { error.clientMessage = "Can't get product releases"; dispatch(productReleasesFetchingError(error)) }); } } … export function updateProductRelease( id, productName, productVersion, releaseDate ) { return dispatch => { dispatch(productReleaseUpdating()); return productReleasesService.updateProductRelease( id, productName, productVersion, releaseDate ).then( productRelease => dispatch(productReleaseUpdated(productRelease)) ).catch(error => { error.clientMessage = "Can't update product releases"; dispatch(productReleaseCreatingUpdatingError(error)) }); } }
Вміст файлу reducers.js до використання Redux Toolkit:
const initialState = { productReleases: [], loadedProductRelease: null, fetchingState: 'none', creatingState: 'none', updatingState: 'none', error: null, }; export default function reducer(state = initialState, action = {}) { switch (action.type) { case productReleases.PRODUCT_RELEASES_FETCHING: return { ...state, fetchingState: 'requesting', error: null, }; case productReleases.PRODUCT_RELEASES_FETCHED: return { ...state, productReleases: action.productReleases, fetchingState: 'success', }; case productReleases.PRODUCT_RELEASES_FETCHING_ERROR: return { ...state, fetchingState: 'failed', error: action.error }; … case productReleases.PRODUCT_RELEASE_UPDATING: return { ...state, updatingState: 'requesting', error: null, }; case productReleases.PRODUCT_RELEASE_UPDATED: return { ...state, updatingState: 'success', productReleases: state.productReleases.map(productRelease => { if (productRelease.id === action.productRelease.id) return action.productRelease; return productRelease; }) }; case productReleases.PRODUCT_RELEASE_UPDATING_ERROR: return { ...state, updatingState: 'failed', error: action.error }; default: return state; } }
Як ми можемо бачити, саме тут міститься більшість бойлерплейта: константи типів дій, творці дій, знову константи, але вже у коді редьюсера на написання всього цього коду доводиться витрачати час. Частково цього бойлерплейту можна позбутися, якщо скористатися функціями createAction
і createReducer
, які також входять до складу Redux Toolkit.
Функція createAction
У наведеній ділянці коду використовується стандартний спосіб визначення дії Redux: спочатку окремо оголошується константа, що визначає тип дії, після чого – функція творця дії цього типу. Функція createAction об’єднує ці об’яви в одне. На вхід вона приймає тип дії та повертає творця дії для цього типу. Автор дії може бути викликаний або без аргументів, або з деяким аргументом (корисне навантаження), значення якого буде поміщено в полі payload, створеного дії. Крім того, автор дії перевизначає функцію toString(), так що тип дії стає його рядковим уявленням.
У деяких випадках може знадобитися написати додаткову логіку для налаштування значення корисного навантаження, наприклад, прийняти кілька параметрів для творця дії, створити випадковий ідентифікатор або отримати поточну мітку. Для цього createAction приймає необов’язковий другий аргумент – функцію, яка використовуватиметься для оновлення значення корисного навантаження. Докладніше про цей параметр можна ознайомитись в офіційній документації.
Використовуючи функцію createAction, отримаємо наступний код:
export const productReleasesFetching = createAction('PRODUCT_RELEASES_FETCHING'); export const productReleasesFetched = createAction('PRODUCT_RELEASES_FETCHED'); export const productReleasesFetchingError = createAction('PRODUCT_RELEASES_FETCHING_ERROR'); … export function fetchProductReleases() { return dispatch => { dispatch(productReleasesFetching()); return productReleasesService.getProductReleases().then( productReleases => dispatch(productReleasesFetched({ productReleases })) ).catch(error => { error.clientMessage = "Can't get product releases"; dispatch(productReleasesFetchingError({ error })) }); } } ...
Функція createReducer
Тепер розглянемо ред’юсер. Як і наш приклад, редьюсери часто реалізуються з допомогою оператора switch, з одним регістром кожному за обробленого типу дії. Цей підхід працює добре, але не позбавлений бойлерплейта і схильний до помилок. Наприклад, легко забути описати випадок default або встановити початковий стан. Функція createReducer спрощує створення функцій редьюсера, визначаючи їх як таблиці пошуку функцій обробки кожного типу дії. Вона також дозволяє суттєво спростити логіку іммутабельного поновлення, написавши код у “мутабельному” стилі всередині ред’юсерів.
“Мутабельний” стиль обробки подій доступний завдяки використанню бібліотеки Immer. Функція обробник може або “мутувати” переданий state для зміни властивостей, або повертати новий state, як при роботі в іммутабельному стилі, але завдяки Immer
реальна мутація об’єкта не здійснюється. Перший варіант набагато простіше для роботи та сприйняття, особливо при зміні об’єкта з глибокою вкладеністю.
Будьте уважні: повернення нового об’єкта із функції перекриває “мутабельні” зміни. Одночасне застосування обох методів поновлення стану не спрацює.
Як вхідні параметри функція createReducer
приймає такі аргументи:
- початковий стан сховища,
- об’єкт, що встановлює відповідність між типами дій та редьюсерами, кожен із яких обробляє якийсь певний тип.
Скориставшись методом createReducer
, отримаємо наступний код:
const initialState = { productReleases: [], loadedProductRelease: null, fetchingState: 'none', creatingState: 'none', loadingState: 'none', error: null, }; const counterReducer = createReducer(initialState, { [productReleasesFetching]: (state, action) => { state.fetchingState = 'requesting' }, [productReleasesFetched.type]: (state, action) => { state.productReleases = action.payload.productReleases; state.fetchingState = 'success'; }, [productReleasesFetchingError]: (state, action) => { state.fetchingState = 'failed'; state.error = action.payload.error; }, … [productReleaseUpdating]: (state) => { state.updatingState = 'requesting' }, [productReleaseUpdated]: (state, action) => { state.updatingState = 'success'; state.productReleases = state.productReleases.map(productRelease => { if (productRelease.id === action.payload.productRelease.id) return action.payload.productRelease; return productRelease; }); }, [productReleaseUpdatingError]: (state, action) => { state.updating = 'failed'; state.error = action.payload.error; }, });
Як бачимо, використання функцій createAction
і createReducer
істотно вирішує проблему написання зайвого коду, але проблема попереднього створення констант все одно залишається. Тому розглянемо більш потужний варіант, що поєднує в собі генерацію і творців дій та редьюсера – функція createSlice
.
Функція createSlice
Як вхідні параметри функція createSlice
приймає об’єкт із наступними полями:
name
– простір імен створюваних дій (${name}/${action.type}
);initialState
– початковий стан ред’юсера;reducers
– об’єкт з обробниками. Кожен обробник приймає функцію з аргументами state і action, action містить у собі дані у властивості payload та ім’я події у властивості name. Крім того, є можливість попередньої зміни даних, отриманих з події, перед їх потраплянням до редьюсера (наприклад, додати id до елементів колекції). Для цього замість функції необхідно передати об’єкт з полями reducer та prepare, де reducer – це функція-обробник дії, а prepare – функція-обробник корисного навантаження, що повертає оновлений payload;extraReducers
– об’єкт, що містить редьюсери іншого зрізу. Цей параметр може знадобитися в разі потреби оновлення об’єкта, що стосується іншого зрізу. Докладніше про цю можливість можна дізнатися з відповідного розділу офіційної документації.
Результатом роботи функції є об’єкт, званий “зріз (slice)”, з наступними полями:
name
– ім’я зрізу,reducer
– ред’юсер,actions
– набір дій.
Використовуючи цю функцію для вирішення нашого завдання, отримаємо наступний вихідний код:
const initialState = { productReleases: [], loadedProductRelease: null, fetchingState: 'none', creatingState: 'none', loadingState: 'none', error: null, }; const productReleases = createSlice({ name: 'productReleases', initialState, reducers: { productReleasesFetching: (state) => { state.fetchingState = 'requesting'; }, productReleasesFetched: (state, action) => { state.productReleases = action.payload.productReleases; state.fetchingState = 'success'; }, productReleasesFetchingError: (state, action) => { state.fetchingState = 'failed'; state.error = action.payload.error; }, … productReleaseUpdating: (state) => { state.updatingState = 'requesting' }, productReleaseUpdated: (state, action) => { state.updatingState = 'success'; state.productReleases = state.productReleases.map(productRelease => { if (productRelease.id === action.payload.productRelease.id) return action.payload.productRelease; return productRelease; }); }, productReleaseUpdatingError: (state, action) => { state.updating = 'failed'; state.error = action.payload.error; }, }, });
Тепер витягнемо із створеного зрізу творці дій та ред’юсер.
const { actions, reducer } = productReleases; export const { productReleasesFetched, productReleasesFetching, productReleasesFetchingError, … productReleaseUpdated, productReleaseUpdating, productReleaseUpdatingError } = actions; export default reducer;
Вихідний код творців дій, що містять виклики API, не змінився, за винятком способу передачі параметрів під час надсилання дій:
export const fetchProductReleases = () => (dispatch) => { dispatch(productReleasesFetching()); return productReleasesService .getProductReleases() .then((productReleases) => dispatch(productReleasesFetched({ productReleases }))) .catch((error) => { error.clientMessage = "Can't get product releases"; dispatch(productReleasesFetchingError({ error })); }); }; … export const updateProductRelease = (id, productName, productVersion, releaseDate) => (dispatch) => { dispatch(productReleaseUpdating()); return productReleasesService .updateProductRelease(id, productName, productVersion, releaseDate) .then((productRelease) => dispatch(productReleaseUpdated({ productRelease }))) .catch((error) => { error.clientMessage = "Can't update product releases"; dispatch(productReleaseUpdatingError({ error })); });
Наведений вище код показує, що функція createSlice
дозволяє позбутися значної частини бойлерплейта при роботі з Redux, що дозволяє не тільки зробити код компактнішим, лаконічнішим і зрозумілішим, але й витрачати менше часу на його написання.
Підсумок
На завершення цієї статті, хотілося б сказати, що незважаючи на те, що бібліотека Redux Toolkit не вносить нічого нового в управління сховищем, вона надає ряд набагато зручніших засобів для написання коду, ніж були до цього. Дані засоби дозволяють не тільки зробити процес розробки більш зручним, зрозумілим і швидким, але і більш ефективним, за рахунок наявності в бібліотеці ряду інструментів, що добре зарекомендували себе раніше.
Переклад статті “Redux Toolkit как средство эффективной Redux-разработки“
Картка Binance тепер підтримує XRP, SHIB і AVAX
- На даний момент картка Binance доступна лише для користувачів Binance, які проживають в ЄЕЗ, і українських біженців, які проживають у країні ЄЕЗ (Binance Refugee Crypto Card ). Ви можете зареєструватися на Binance Card тут .
- Станом на 07:00 (UTC) 2022-08-05 на Binance Card є 14 підтримуваних криптовалют: ADA, AVAX, BNB, BTC, BUSD, DOT, ETH, LAZIO, PORTO, SANTOS, SHIB, SXP, USDT і XRP .
- Щоб витратити нещодавно підтримані криптовалюти за допомогою Binance Card, перейдіть до Інформаційної панелі картки > Пріоритет платежу > Редагувати, щоб додати, видалити або ранжувати криптовалюти для витрат відповідно до власних уподобань.
- Користувачі повинні мати принаймні шість криптовалют у списку пріоритетів платежів. Можна вибрати максимум 12 криптовалют.
- З додаванням XRP, SHIB і AVAX до Binance Card поточні параметри пріоритету платежу для наявних користувачів картки Binance не зміняться.
- Binance Card випускається ліцензованою організацією UAB «Finansinės paslaugos Contis» і розповсюджується Swipe. Використання вами Binance Card регулюється умовами, викладеними в Угоді власника картки.
React Storybook
За допомогою React Storybook ви можете розробляти та проектувати компоненти інтерфейсу користувача за межами вашої програми в ізольованому середовищі. Це змінить спосіб розробки компонентів інтерфейсу користувача.
Перш ніж ми почнемо
Сьогодні серверні системи стали дуже простими завдяки фреймворкам, таким як Meteor, і хмарним службам, таким як Firebase. Такі речі, як GraphQL і Falcor виведе серверні системи на новий рівень.
Отже, ми витрачаємо багато часу на створення програм на стороні клієнта, а не на роботу над серверною частиною. React змінив спосіб створення користувацьких інтерфейсів, але нам все ще потрібно наполегливо працювати, щоб створювати чудові користувацькі інтерфейси. Для цього ми пишемо багато коду на стороні клієнта, а не на стороні сервера.
Просто порахуйте КІЛЬКІСТЬ РЯДКІВ , які ви написали для СТОРОНИ КЛІЄНТА, і ви зрозумієте, що я маю на увазі.
Навіть у програмі на стороні клієнта більшу частину часу ми зосереджуємося на створенні кількох компонентів інтерфейсу користувача, і вони зазвичай не мають нічого спільного з рештою програми. Навіть коли ви впроваджуєте нові функції, багато часу витрачається на створення компонентів інтерфейсу користувача.
Це важко
Завдяки гарячому перезавантаженню ми можемо дуже швидко розробляти та ітерувати інтерфейс користувача. Зазвичай ми робимо це в нашому додатку.
Але побудувати компонент у програмі важко. Дозвольте мені показати вам проблему.
Уявіть, що ми створюємо компонент списку завдань. Отже, він має кілька станів, і нам потрібно змінити інтерфейс для них. Ось список штатів:
- У списку немає елементів.
- У списку є кілька елементів (він не порожній).
- Деякі з цих пунктів завершено.
- Усі пункти в списку виконано.
Навіть якщо ми знайдемо спосіб відтворити ці стани всередині програми, нам потрібно якось їх задокументувати. Інакше новий розробник або дизайнер не зможе працювати над цими компонентами інтерфейсу користувача.
Я можу перерахувати багато таких проблем, як це. Але, я сподіваюся, ви зрозуміли суть.
Зустрічайте React Storybook
Ми намагаємося вирішити більшість вищевказаних проблем за допомогою React Storybook . Використовуючи його, ви можете розробляти компоненти інтерфейсу користувача за межами програми та дозволяти іншим людям у вашій команді працювати над ними.
Після налаштування ви можете запустити консоль React Storybook, ввівши:
npm run book story
Потім він запустить веб-сервер на порту 9001 і виглядає так:
Після цього нам потрібно помістити наші компоненти (з їхніми різними станами ) у наведену вище консоль. Ми робимо це, пишучи набір історій.
Одна STORY має повертати елемент REACT. Потім ви взаємодієте з ним із React Storybook.
У наступному коді ми пишемо кілька історій для різних станів нашого компонента списку завдань.
(Тут наш компонент списку завдань називається «MainSection»)
import React from 'react'; import MainSection from '../MainSection'; import { storiesOf, action } from '@storybook'; storiesOf('MainSection', module) .add('all active', () => { const todoItems = [ { id: 'one', text: 'Item One', completed: false }, { id: 'two', text: 'Item Two', completed: false }, ]; return getMainSection(todoItems); }) .add('some completed', () => { const todoItems = [ { id: 'one', text: 'Item One', completed: false }, { id: 'two', text: 'Item Two', completed: true }, ]; return getMainSection(todoItems); }) .add('all completed', () => { const todoItems = [ { id: 'one', text: 'Item One', completed: true }, { id: 'two', text: 'Item Two', completed: true }, ]; return getMainSection(todoItems); }); function getMainSection(todos) { const actions = { clearCompleted: action('clearCompleted'), completeAll: action('completeAll') }; return (
); }
Тоді ти маєш змогу взаємодіяти з ними у React Storybook ось так:
Отже, інші у вашій команді можуть надати вам відгуки про ці компоненти інтерфейсу користувача. Крім того, дизайнери у вашій команді хотіли б попрацювати над цими компонентами інтерфейсу користувача та зробити їх гарним.
Переклад статті “Introducing React Storybook“
Binance Card для біженців із України
Binance запустила Binance Card для біженців із України, які були змушені переїхати до країн ЄЕЗ через війну з Росією 📣🇺🇦
Binance Card створена у партнерстві з Contis. Це дозволить переміщеним українцям здійснювати або отримувати криптоплатежі та здійснювати купівлю в роздрібних торгових точках в ЄЕЗ, які приймають оплату карткою.
🙏🏻 Binance Charity співпрацює з різними неурядовими організаціями, щоб надати грошову допомогу за допомогою Binance Card для біженців. До слова, створений Binance «Фонд екстреної допомоги Україні» уже зібрав більше $1 млн.
📩 Отримання та використання віртуальної та фізичної Binance Card безкоштовне. Щоб отримати картку, біженцям потрібно мати або зареєструвати акаунт на Binance, пройти повну верифікацію за українським документом та прив’язати до акаунта європейський номер телефона. Для отримання картки використовуйте вашу поточну адресу у країні ЄЕЗ.
➡️ Гайд із замовлення Binance Card
Також слід зазначити, що біженці, які звернулися до місцевих некомерційних організацій та подали заявку на отримання криптовалютних карток Binance Refugee Card, отримають 75 BUSD (1 BUSD = $1) щомісно (225 BUSD протягом трьох місяців) як підтримку від біржі.
Figma plugin API людською мовою
Зіткнувся з написанням плагіна для Figma і дивуюся, навіщо так складно? Ну, взагалі-то, нічого особливо складного немає. Але цей TypeScript, це навіщо все? Встанови модулі, налаштуйте публікацію. Скільки я не думав, єдине пояснення, навіщо все це потрібне, це захист від дурня. Типу, кому треба – розбереться, а іншим і нема чого лізти, говнокод плодити.
Ну так ми розвіємо цей снобістський тренд і прорубаємо шлях в API Figma для всіх бажаючих.
Суть у тому, що якщо відкинути все зайве, то в сухому залишку нам знадобиться лише три файли:
Точкою входу плагіна є файл manifest.json. Виглядати він має так:
{
"name": "Simple Plugin",
"api": "1.0.0",
"main": "plugin.js",
"ui": "index.html",
"editorType": [
"figma"
]
}
Поле name це ім’я плагіна, воно буде відображатися в меню і на корінці вікна плагіна.
У полі api ми вказуємо версію api, поки це 1.0.0.
Поле editorType містить масив із перерахуванням редакторів, для яких розробляється плагін. Ми вказуємо лише figma.
Два поля main і ui, що залишилися, містять шляхи до файлів самого плагіна. ui вказує на html з версткою та логікою вікна плагіна. main посилається на js з логікою взаємодії плагіна з Figma.
Почнемо їх вивчення з ui, а значить із файлу index.html:
<button>Click Me</button>
<script>
document.querySelector('button').onclick = () => {
alert('Hello world!!!')
}
</script>
Я помістив у нього кнопку та скрипт, що обробляє клік по цій кнопці. Натиснувши кнопку, виводиться вікно з текстом “Hello World!!!”. Тут важливо зрозуміти, що скрипт повинен перебувати усередині html. Підвантажувати скрипт атрибутом src плагін не вміє.
Ну, і останній файл, який нам потрібен для роботи плагіна, це plugin.js.
figma.showUI (
__html__,
{width: 400, height: 400}
);
Він дуже простий, в ньому ми тільки даємо Figma команду, відкрити вікно з вмістом нашого html. Другим параметром метод showUI приймає об’єкт, у якому ми вказуємо необхідний розмір вікна.
Ось, власне, і все. Нам залишилося лише відкрити редактор Figma та перейти в меню Plugins -> Development -> Import plugin from manifest…
Вибираємо наш manifest.json, після чого в тому ж меню знаходимо наш плагін.
Наш плагін готовий.
З документацією API Figma можна познайомитись тут.
AIRDROP – або як заробити на нових токенах
AIRDROP у крипті це не те що AIRDROP на iOS 🙂 AIRDROP – це безкоштовна роздача нових токенів (ну або умовна безкоштовна). Нові токени роздають, коли хочуть отримати у свій новий проект користувачів. Як правило, це досить вигідно. Хоча токени видаються не одразу, а частинами. як правило протягом року або півроку.
Умовно кажучи, вкладаючи 10$ ви отримуєте через певний час якусь кількість токенів (які зазвичай недооцінені) на 20$. І в момент їхнього лістингу на біржі продаєте в перші 5 – 10 хвилин. У піку зростання.
У цьому відношенні дуже вигідно, коли AIRDROP відбувається на біржі. Яка випускає свій токен, який потім використовується для торгівлі на біржі та оплати комісій. (Наприклад, на binance це BNB ). Так ось у момент лістингу токена на своїй біржі він зазвичай у перші 5 хвилин торгів дорожчає в десятки разів. Оскільки біржа викуповує ці токени. Викуповує (як правило для спалювання, щоб підняти ціну) тому що основне завдання цих токенів було залучити нових користувачів до проекту. І на початку торгів можна нормально заробити.
Зараз якраз на горизонті з’явився цікавий AIRDROP нової української біржі QMALL . Тож якщо комусь цікаво, то можуть взяти участь. У цьому AIRDROP можна отримати токени QML за виконання простих дій. Які можна буде почати продувати 15.02.2022. Детальніше можна подивитися тут
Всі удачі та будьте обережні при інвестуванні в крипту.