Оптимізація React-додатків: Використовуємо useTransition, useDeferredValue та useOptimistic для плавного UI
Сучасні React-додатки часто мають складний інтерфейс із динамічними елементами, що взаємодіють із користувачем у реальному часі. Оптимізація продуктивності таких додатків є важливою задачею, особливо для забезпечення плавного користувацького досвіду. У цьому контексті React надає корисні інструменти: useTransition, useDeferredValue та useOptimistic. Розглянемо, як їх використовувати.
Що таке useTransition?
useTransition — це хук, який дозволяє позначати частину оновлень у React як “незначущі”. Це означає, що такі оновлення не будуть блокувати основний інтерфейс користувача, навіть якщо вони займають більше часу.
Приклад використання useTransition
Уявімо, що у нас є додаток із великим списком, який користувач може фільтрувати:
import { useState, useTransition } from 'react';
function FilterableList({ items }) {
const [filter, setFilter] = useState('');
const [filteredItems, setFilteredItems] = useState(items);
const [isPending, startTransition] = useTransition();
const handleFilterChange = (e) => {
const value = e.target.value;
setFilter(value);
startTransition(() => {
const newFilteredItems = items.filter(item => item.includes(value));
setFilteredItems(newFilteredItems);
});
};
return (
<div>
<input value={filter} onChange={handleFilterChange} placeholder="Фільтрувати..." />
{isPending && <div>Завантаження...</div>}
<ul>
{filteredItems.map((item, index) => <li key={index}>{item}</li>)}
</ul>
</div>
);
}
Як це працює
startTransition використовується для запуску “незначущих” оновлень.
isPending показує, чи триває транзакція.
- Основний інтерфейс, наприклад, введення тексту у поле, залишається плавним, навіть якщо фільтрація займає багато часу.
Що таке useDeferredValue?
useDeferredValue дозволяє відкладати оновлення значення до моменту, коли браузер буде готовий виконати його, не впливаючи на продуктивність основного інтерфейсу.
Приклад використання useDeferredValue
Припустимо, що у нас є компонент для пошуку, який відображає результати в режимі реального часу:
import { useState, useDeferredValue } from 'react';
function Search({ items }) {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
const results = items.filter(item => item.includes(deferredQuery));
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Пошук..."
/>
<ul>
{results.map((item, index) => <li key={index}>{item}</li>)}
</ul>
</div>
);
}
Як це працює
useDeferredValue створює відкладену версію значення query.
- Це дозволяє браузеру спочатку обробити термінові оновлення, такі як введення тексту, а вже потім виконати пошук.
Що таке useOptimistic?
useOptimistic — це хук, який допомагає створювати оптимістичні оновлення стану. Це означає, що зміни в UI будуть відображені одразу, ще до завершення операції (наприклад, запиту на сервер).
Приклад використання useOptimistic
Припустимо, у нас є кнопка, яка додає елемент до списку:
import { useOptimistic } from 'react';
function OptimisticList() {
const [list, setList] = useOptimistic([], (prev, newItem) => [...prev, newItem]);
const handleAddItem = async () => {
const newItem = `Item ${list.length + 1}`;
setList(newItem);
// Симуляція запиту на сервер
await fetch('/api/add-item', {
method: 'POST',
body: JSON.stringify({ item: newItem }),
});
};
return (
<div>
<button onClick={handleAddItem}>Додати елемент</button>
<ul>
{list.map((item, index) => <li key={index}>{item}</li>)}
</ul>
</div>
);
}
Як це працює
useOptimistic дозволяє відобразити новий елемент у списку одразу після натискання кнопки.
- Якщо сервер поверне помилку, ви можете відкотити зміни.
Коли використовувати ці інструменти?
useTransition: коли ви хочете розділити важкі обчислення або оновлення стану від термінових подій, таких як введення тексту.
useDeferredValue: для покращення продуктивності компонентів, які залежать від значення, що часто змінюється.
useOptimistic: для створення швидкої та інтерактивної взаємодії з користувачем у ситуаціях, коли серверна операція може займати час.
Висновок
React пропонує потужні інструменти для оптимізації взаємодії з користувачем, особливо у додатках, де продуктивність є ключовою. Використання useTransition, useDeferredValue та useOptimistic дозволяє забезпечити плавний та швидкий UI, одночасно спрощуючи обробку складних обчислень та запитів. Застосовуючи ці інструменти у ваших проектах, ви зможете значно покращити користувацький досвід та продуктивність вашого додатку.
Чому важливо перевіряти response.ok у Fetch API
Коли ми працюємо з Fetch API у JavaScript, часто здається, що достатньо просто виконати запит і обробити отриманий результат. Однак Fetch API не завжди поводиться так, як можна очікувати. Перевірка властивості response.ok є одним із ключових аспектів роботи з цим API, що допомагає уникнути поширених помилок і забезпечити стабільність вашого коду.
Що таке Fetch API?
Fetch API — це сучасний стандарт для виконання HTTP-запитів у браузерах. Він дозволяє відправляти запити на сервер та отримувати відповіді, використовуючи обіцянки (Promises), що значно спрощує асинхронну роботу в порівнянні зі старими методами, такими як XMLHttpRequest.
Простий приклад використання Fetch API:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
На перший погляд, усе виглядає чудово. Але тут виникає важливий нюанс: Fetch API вважає успішним будь-який запит, який отримав відповідь від сервера, навіть якщо сервер повернув статус помилки, наприклад, 404 Not Found або 500 Internal Server Error.
Що таке response.ok?
response.ok — це булева властивість об’єкта Response, яка повертає true, якщо статус відповіді знаходиться в діапазоні від 200 до 299. Це вказує на те, що запит було виконано успішно.
Ось приклад використання:
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Чому це важливо?
- Обробка помилок на сервері Сервер може повернути статуси, які вказують на помилки (наприклад,
404, 403, 500), але Fetch API все одно вважає запит успішним. Якщо ви не перевіряєте response.ok, ваш код може некоректно обробляти ці відповіді.fetch('https://api.example.com/missing-endpoint')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
У цьому випадку додаток може вивести некоректні дані або взагалі зламатися.
- Покращення стабільності додатку Перевірка
response.ok дозволяє заздалегідь виявити та обробити помилки, які можуть виникнути під час запиту. Наприклад, якщо сервер повертає статус 403 Forbidden, можна одразу показати користувачу відповідне повідомлення.
- Зрозуміліше налагодження Якщо ви перевіряєте
response.ok, ви можете створювати докладніші повідомлення про помилки, які допомагають швидше знаходити та виправляти проблеми.
- Поліпшення UX Коли користувач взаємодіє з вашим додатком, він очікує, що система правильно реагуватиме на помилки. Наприклад, якщо сервер повертає
404 Not Found, ваш додаток може показати повідомлення на кшталт “Ресурс не знайдено”, замість того, щоб просто зламатися.
Як правильно використовувати response.ok?
Ось приклад правильної обробки запитів із перевіркою response.ok:
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error.message);
return null;
}
}
fetchData('https://api.example.com/data')
.then(data => {
if (data) {
console.log('Отримані дані:', data);
} else {
console.log('Не вдалося отримати дані.');
}
});
Часті помилки та як їх уникнути
- Ігнорування статусу відповіді Часто розробники працюють із даними без перевірки статусу відповіді, що може призвести до непередбачуваної поведінки.Як виправити: Завжди перевіряйте
response.ok перед обробкою даних.
- Обробка лише успішних запитів Інколи розробники забувають обробляти помилки, через що користувачі можуть залишатися в невідомості щодо проблеми.Як виправити: Використовуйте
catch або інші механізми для відображення помилок.
- Неправильна обробка статусів Деякі розробники вважають, що всі статуси в межах
2xx гарантують успіх. Однак, навіть у цьому діапазоні можуть бути статуси, що потребують додаткової уваги (наприклад, 204 No Content).
Висновок
Перевірка response.ok у Fetch API — це найкраща практика, яка дозволяє уникнути багатьох проблем під час роботи з HTTP-запитами. Вона забезпечує стабільність вашого додатку, покращує користувацький досвід та полегшує налагодження коду.
Пам’ятайте, що Fetch API лише доставляє відповідь від сервера, але перевірка успішності цієї відповіді залишається вашою відповідальністю. Завжди додавайте перевірку response.ok, щоб створити надійні та зручні для користувачів веб-додатки.
Що таке показник FDV та як він впливає на ціни криптоактивів?
У світі криптовалют існує безліч метрик, які допомагають інвесторам оцінювати проєкти та приймати зважені рішення щодо інвестицій. Однією з таких метрик є FDV (Fully Diluted Valuation) або повністю розбавлена оцінка. Ця стаття розкриє суть показника FDV, його значення та вплив на ціни криптоактивів.
Що таке FDV?
FDV, або повністю розбавлена оцінка, є показником, який демонструє теоретичну ринкову капіталізацію криптовалюти, якщо всі її токени будуть випущені в обіг. Формула для розрахунку FDV виглядає так:
FDV = Поточна ціна токена × Загальна кількість токенів (максимальна емісія)
Цей показник враховує не лише токени, які вже перебувають в обігу, але й ті, що можуть бути випущені в майбутньому (наприклад, через стейкінг, майнінг або заплановане розподілення серед команди та інвесторів).
FDV проти ринкової капіталізації
Щоб краще зрозуміти FDV, важливо розрізняти його та ринкову капіталізацію (Market Cap):
- Ринкова капіталізація враховує тільки ті токени, які вже перебувають в обігу.\n
Формула:
Market Cap = Поточна ціна токена × Кількість токенів в обігу
- FDV — це більш широкий показник, який враховує потенційну максимальну кількість токенів.
Наприклад, якщо в проєкту є 10 мільйонів токенів, але в обігу наразі лише 1 мільйон, то ринкова капіталізація буде значно меншою за FDV. Це може створити у інвесторів викривлене уявлення про реальну оцінку проєкту.
Чому FDV важливий?
FDV допомагає інвесторам оцінити потенційну вартість проєкту в довгостроковій перспективі. Він особливо корисний для аналізу криптовалют, які ще не випустили всі свої токени.
Основні причини використовувати FDV:
- Оцінка ризиків: Якщо FDV значно перевищує ринкову капіталізацію, це може свідчити про можливий ризик інфляції ціни токенів через їхнє поступове випускання.
- Довгострокова перспектива: Інвестори можуть оцінити, наскільки масштабним буде проєкт після випуску всіх токенів.
- Порівняння проєктів: FDV дозволяє краще порівнювати проєкти з різною кількістю токенів в обігу.
Як FDV впливає на ціни криптоактивів?
FDV може впливати на ціни криптоактивів як безпосередньо, так і опосередковано. Розгляньмо основні чинники впливу.
1. Розбавлення вартості
Коли криптовалюта поступово випускає нові токени, поточні інвестори можуть відчути зниження своєї частки у загальному обсязі токенів. Це явище називають розбавленням (dilution). Розбавлення може призвести до зниження ціни токена, якщо попит залишиться незмінним.
2. Очікування ринку
Інвестори, які знають про високий FDV, можуть бути обережними щодо інвестицій у проєкт, побоюючись майбутнього зростання кількості токенів. Це може знизити попит, що, у свою чергу, тисне на ціну.
3. Довіра до проєкту
FDV також впливає на те, як ринок сприймає криптовалюту. Наприклад, якщо проєкт має дуже високий FDV, але малу ринкову капіталізацію, це може викликати питання щодо реалістичності його оцінки.
Переваги та недоліки використання FDV
Переваги:
- Глобальна оцінка: FDV дає ширше уявлення про потенційну вартість проєкту.\n
- Прогнозування ризиків: Інвестори можуть оцінити ризик майбутнього випуску токенів.
- Порівняння: FDV дозволяє порівнювати проєкти навіть на ранніх стадіях.
Недоліки:
- Не враховує попит: FDV розраховується виключно на основі кількості токенів і їхньої ціни, не враховуючи попит чи ринкову динаміку.
- Може вводити в оману: Високий FDV не завжди означає, що проєкт має реальну цінність.
Приклади FDV у реальних проєктах
Ethereum (ETH)
У Ethereum максимальна кількість токенів не обмежена, тому FDV не застосовується в класичному вигляді. Але ринкова капіталізація дозволяє оцінити його поточну вартість.
Solana (SOL)
Solana має фіксовану максимальну кількість токенів, тому FDV дозволяє оцінити повний потенціал проєкту.
Shiba Inu (SHIB)
Через величезну кількість токенів FDV Shiba Inu часто викликає сумніви у серйозних інвесторів, адже велика кількість токенів може створити ризики надмірного розбавлення.
Як інвесторам використовувати FDV?
- Порівнюйте FDV із ринковою капіталізацією. Це допоможе зрозуміти, наскільки проєкт залежить від майбутнього випуску токенів.\n
- Оцінюйте дорожню карту. Дізнайтеся, коли і як будуть випускатися нові токени.\n
- Аналізуйте попит. Високий FDV не є проблемою, якщо проєкт має сильну підтримку спільноти та високий попит.
Висновок
Показник FDV є важливим інструментом для оцінки потенційної вартості криптопроєктів. Хоча він не є абсолютним показником успіху чи ризику, він допомагає інвесторам краще розуміти довгострокову перспективу криптоактивів. Розуміння FDV у поєднанні з іншими метриками, такими як ринкова капіталізація та попит, дозволяє приймати обґрунтовані інвестиційні рішення.
Як створити тестувальник навантаження для API на Node.js
Тестування навантаження — це важлива складова процесу розробки, яка допомагає переконатися, що ваш API витримує високе навантаження та працює стабільно за різних умов. Одним із популярних інструментів для створення кастомних тестувальників є платформа Node.js, яка завдяки своїй асинхронній природі та високій продуктивності чудово підходить для таких завдань.
У цій статті ми розглянемо, як створити власний тестувальник навантаження для API, використовуючи Node.js. Ми створимо скрипт, який зможе надсилати велику кількість запитів до API, аналізувати результати та генерувати звіти про продуктивність.
Основні кроки створення тестувальника
- Вибір інструментів.
- Налаштування середовища Node.js.
- Створення базової структури скрипта.
- Надсилання HTTP-запитів до API.
- Вимірювання продуктивності.
- Генерація звітів.
1. Вибір інструментів
Для реалізації тестувальника ми будемо використовувати наступні бібліотеки:
- Axios: для відправки HTTP-запитів.
- Perf Hooks: для вимірювання часу виконання запитів.
- fs: для збереження результатів у файл.
- dotenv: для роботи зі змінними середовища.
Встановіть їх за допомогою npm:
npm install axios dotenv
2. Налаштування середовища Node.js
Створіть новий проект та налаштуйте середовище:
mkdir load-tester
cd load-tester
npm init -y
Створіть файл .env для зберігання параметрів API:
API_URL=https://your-api-endpoint.com
REQUESTS=1000
CONCURRENT_USERS=50
3. Створення базової структури скрипта
Створіть файл index.js та додайте базову структуру:
require('dotenv').config();
const axios = require('axios');
const { performance } = require('perf_hooks');
const API_URL = process.env.API_URL;
const TOTAL_REQUESTS = parseInt(process.env.REQUESTS, 10);
const CONCURRENT_USERS = parseInt(process.env.CONCURRENT_USERS, 10);
let results = [];
const main = async () => {
console.log(`Starting load test with ${TOTAL_REQUESTS} requests and ${CONCURRENT_USERS} concurrent users.`);
// Логіка тестування буде тут
};
main();
4. Надсилання HTTP-запитів до API
Додамо функцію для відправки запитів та обробки відповідей:
const sendRequest = async () => {
const start = performance.now();
try {
const response = await axios.get(API_URL);
const end = performance.now();
return {
success: true,
status: response.status,
time: end - start,
};
} catch (error) {
const end = performance.now();
return {
success: false,
status: error.response ? error.response.status : 'NETWORK_ERROR',
time: end - start,
};
}
};
Додамо функцію для одночасного запуску кількох запитів:
const runLoadTest = async () => {
const promises = Array.from({ length: CONCURRENT_USERS }, async () => {
for (let i = 0; i < TOTAL_REQUESTS / CONCURRENT_USERS; i++) {
const result = await sendRequest();
results.push(result);
}
});
await Promise.all(promises);
};
5. Вимірювання продуктивності
В кінці тесту ми зберемо статистику, яка допоможе оцінити продуктивність API:
const analyzeResults = () => {
const totalRequests = results.length;
const successCount = results.filter((r) => r.success).length;
const failureCount = totalRequests - successCount;
const averageTime = results.reduce((sum, r) => sum + r.time, 0) / totalRequests;
console.log(`\nTest Results:`);
console.log(`Total Requests: ${totalRequests}`);
console.log(`Successful Requests: ${successCount}`);
console.log(`Failed Requests: ${failureCount}`);
console.log(`Average Response Time: ${averageTime.toFixed(2)} ms`);
};
6. Генерація звітів
Додамо функцію для збереження результатів у файл:
const fs = require('fs');
const saveResults = () => {
const report = {
timestamp: new Date().toISOString(),
totalRequests: results.length,
results,
};
fs.writeFileSync('report.json', JSON.stringify(report, null, 2));
console.log('Report saved to report.json');
};
Оновимо функцію main:
const main = async () => {
console.log(`Starting load test with ${TOTAL_REQUESTS} requests and ${CONCURRENT_USERS} concurrent users.`);
await runLoadTest();
analyzeResults();
saveResults();
};
main();
Повний код скрипта
Ваш файл index.js має виглядати так:
require('dotenv').config();
const axios = require('axios');
const { performance } = require('perf_hooks');
const fs = require('fs');
const API_URL = process.env.API_URL;
const TOTAL_REQUESTS = parseInt(process.env.REQUESTS, 10);
const CONCURRENT_USERS = parseInt(process.env.CONCURRENT_USERS, 10);
let results = [];
const sendRequest = async () => {
const start = performance.now();
try {
const response = await axios.get(API_URL);
const end = performance.now();
return {
success: true,
status: response.status,
time: end - start,
};
} catch (error) {
const end = performance.now();
return {
success: false,
status: error.response ? error.response.status : 'NETWORK_ERROR',
time: end - start,
};
}
};
const runLoadTest = async () => {
const promises = Array.from({ length: CONCURRENT_USERS }, async () => {
for (let i = 0; i < TOTAL_REQUESTS / CONCURRENT_USERS; i++) {
const result = await sendRequest();
results.push(result);
}
});
await Promise.all(promises);
};
const analyzeResults = () => {
const totalRequests = results.length;
const successCount = results.filter((r) => r.success).length;
const failureCount = totalRequests - successCount;
const averageTime = results.reduce((sum, r) => sum + r.time, 0) / totalRequests;
console.log(`\nTest Results:`);
console.log(`Total Requests: ${totalRequests}`);
console.log(`Successful Requests: ${successCount}`);
console.log(`Failed Requests: ${failureCount}`);
console.log(`Average Response Time: ${averageTime.toFixed(2)} ms`);
};
const saveResults = () => {
const report = {
timestamp: new Date().toISOString(),
totalRequests: results.length,
results,
};
fs.writeFileSync('report.json', JSON.stringify(report, null, 2));
console.log('Report saved to report.json');
};
const main = async () => {
console.log(`Starting load test with ${TOTAL_REQUESTS} requests and ${CONCURRENT_USERS} concurrent users.`);
await runLoadTest();
analyzeResults();
saveResults();
};
main();
Висновок
Створення тестувальника навантаження на Node.js є ефективним підходом для глибокого аналізу продуктивності API. Цей інструмент дозволяє ідентифікувати слабкі місця вашого сервісу, забезпечуючи надійну роботу під час високих навантажень. Розуміння основних принципів роботи та гнучкість Node.js дають можливість створити потужний кастомний інструмент, який буде відповідати вашим потребам.
useActionState у світі React: Управління діями та станом компонентів.

React — це популярна бібліотека для створення інтерфейсів користувача, яка надає розробникам гнучкість у роботі зі станом та діями компонентів. Одним із сучасних підходів до управління станом є використання спеціальних хуків, таких як useState, useReducer і useContext. Але інколи виникає потреба створити більш гнучкий механізм для управління станом і діями. У таких випадках з’являється концепція “useActionState”.
У цій статті ми розглянемо, що таке useActionState, як він допомагає ефективніше управляти станом у React-додатках, і як його використовувати для оптимізації компонентів. Хоча useActionState не є вбудованим хуком React, ми покажемо, як його реалізувати і застосовувати.
Що таке useActionState?
useActionState — це паттерн або кастомний хук, який об’єднує логіку управління станом та діями в одному місці. Замість того, щоб окремо працювати з useState для стану та вручну створювати функції для обробки дій, useActionState дозволяє:
- Описувати стан і дії разом.
- Забезпечувати кращу читабельність і масштабованість коду.
- Уникати розпорошення логіки між різними хуками або компонентами.
Як це працює?
useActionState базується на принципах хуків React, таких як useReducer. Основна ідея — створити механізм, де стан і функції-обробники взаємодіють через простий API.
Простий приклад виглядає так:
const useActionState = (initialState, actions) => {
const [state, setState] = React.useState(initialState);
const boundActions = {};
for (const key in actions) {
boundActions[key] = (...args) => {
const result = actions[key](state, ...args);
setState(result);
};
}
return [state, boundActions];
};
Як створити useActionState?
Розглянемо реалізацію useActionState на прикладі.
Крок 1: Опис початкового стану та дій
const initialState = {
count: 0,
};
const actions = {
increment: (state, amount = 1) => ({ count: state.count + amount }),
decrement: (state, amount = 1) => ({ count: state.count - amount }),
reset: () => ({ count: 0 }),
};
Крок 2: Використання кастомного хуку у компоненті
const Counter = () => {
const [state, actions] = useActionState(initialState, actions);
return (
<div>
<h1>Count: {state.count}</h1>
<button onClick={() => actions.increment(1)}>Increment</button>
<button onClick={() => actions.decrement(1)}>Decrement</button>
<button onClick={actions.reset}>Reset</button>
</div>
);
};
У цьому прикладі ми:
- Використовуємо useActionState для керування станом лічильника.
- Описуємо логіку дій (increment, decrement, reset) в одному об’єкті
actions.
- Передаємо ці дії разом зі станом у компонент.
Переваги використання useActionState
1. Краща структура коду
Використовуючи useActionState, ви тримаєте стан і логіку його змін разом. Це дозволяє уникати дублювання коду й полегшує підтримку.
2. Масштабованість
Якщо ваш додаток зростає, ви можете легко додати нові дії без необхідності змінювати основний хук чи логику компонентів.
3. Легкість тестування
Ви можете окремо тестувати функції дій, які визначені у об’єкті actions. Це знижує кількість помилок при внесенні змін.
Порівняння useActionState з useReducer
useReducer — це вбудований хук React, який також дозволяє управляти складним станом через редюсери. Однак useActionState надає більш зрозумілий і декларативний підхід для управління простими станами та діями.
| Характеристика |
useReducer |
useActionState |
| Складність API |
Вимагає створення редюсера та dispatch-функцій |
Простий об’єкт дій |
| Читабельність |
Менш зрозумілий для новачків |
Інтуїтивно зрозумілий |
| Гнучкість |
Підходить для складних станів |
Оптимальний для простих та середніх станів |
Використання у реальних проєктах
useActionState найкраще підходить для:
- Малих і середніх додатків:
- Де немає потреби у складних глобальних станах, як-от Redux чи Context API.
- Форм:
- Управління станом полів введення, помилок і валідації.
- Компонентів з локальним станом:
- Наприклад, модальних вікон або вкладок.
Приклад використання у формі:
const formActions = {
updateField: (state, field, value) => ({
...state,
[field]: value,
}),
resetForm: () => ({ name: '', email: '' }),
};
const Form = () => {
const [formState, formHandlers] = useActionState({ name: '', email: '' }, formActions);
return (
<form>
<input
type="text"
value={formState.name}
onChange={(e) => formHandlers.updateField('name', e.target.value)}
/>
<input
type="email"
value={formState.email}
onChange={(e) => formHandlers.updateField('email', e.target.value)}
/>
<button type="button" onClick={formHandlers.resetForm}>Reset</button>
</form>
);
};
Висновок
useActionState — це гнучкий підхід до управління станом у React, який поєднує простоту та функціональність. Завдяки йому ви можете уникати зайвого дублювання коду та створювати більш підтримувані й масштабовані додатки.
Він не замінює існуючі інструменти, такі як useReducer чи Redux, але стає чудовим вибором для роботи з локальним станом у компонентах. Спробуйте впровадити цей паттерн у своїх проєктах, щоб зробити їх більш зрозумілими та ефективними.
Що таке IPFS протокол?

IPFS (InterPlanetary File System) — це децентралізований протокол і одночасно файловий протокол, що дозволяє зберігати та обмінюватися даними у розподіленій мережі. Його головна мета — створити більш відкритий, швидкий і безпечний спосіб зберігання та передачі інформації в інтернеті. На відміну від традиційних моделей, які базуються на центральних серверах, IPFS пропонує принципово новий підхід до управління даними.
Як працює IPFS?
Основою IPFS є технологія розподіленого хешування (DHT) та використання однорангових мереж (peer-to-peer). Це дозволяє користувачам безпосередньо з’єднуватися один з одним для обміну файлами без посередників.
Основні принципи роботи:
- Адресація через вміст (content addressing):
- Замість адресації за місцем розташування (наприклад, URL), IPFS використовує унікальні хеші для кожного файлу. Ці хеші створюються на основі вмісту файлу, тому будь-яка зміна в ньому змінює і його хеш.
- Розподілене зберігання:
- Файли розбиваються на блоки, які зберігаються на різних вузлах мережі. Це дозволяє уникнути залежності від єдиного сервера.
- Peer-to-peer обмін:
- Кожен користувач мережі IPFS може бути як клієнтом, так і сервером. Ви отримуєте файли від інших користувачів і можете надавати доступ до своїх.
- Кешування та дублювання:
- IPFS кешує дані локально, що знижує затримки та зменшує навантаження на мережу. Також дані можуть дублюватися на декількох вузлах для забезпечення доступності.
- IPNS (InterPlanetary Name System):
- Це система імен, яка дозволяє створювати постійні посилання на змінюваний вміст, оскільки базовий IPFS-адрес не змінюється лише тоді, коли вміст статичний.
Основні переваги IPFS
1. Децентралізація:
IPFS усуває потребу в центральних серверах, що знижує ризик збоїв через перевантаження або відмову серверів.
2. Продуктивність:
Файли доставляються з найближчих вузлів мережі, що підвищує швидкість завантаження.
3. Безпека:
IPFS використовує криптографічні хеші для перевірки автентичності даних. Це гарантує, що отриманий вміст не був змінений чи підроблений.
4. Стійкість до цензури:
Через розподілений характер мережі цензура або блокування даних стає майже неможливим.
5. Економічність:
IPFS дозволяє зменшити витрати на зберігання, оскільки файли розміщуються на багатьох вузлах без централізованих серверів.
Приклади використання IPFS
1. Децентралізовані вебсайти:
Вебсайти на основі IPFS зберігаються у вигляді розподілених даних, що робить їх стійкими до атак DDoS і цензури.
2. Зберігання великих даних:
Організації можуть використовувати IPFS для зберігання великих обсягів даних з можливістю доступу до них з будь-якого вузла мережі.
3. NFT і блокчейн:
Багато платформ NFT використовують IPFS для зберігання метаданих і медіа-файлів, оскільки це забезпечує надійність та довговічність даних.
4. Наукові дані та архіви:
IPFS забезпечує доступ до наукових досліджень, архівів і книг навіть у разі виходу з ладу центрального сервера.
Порівняння з традиційним інтернетом
| Характеристика |
Традиційний Інтернет |
IPFS |
| Адресація |
За місцем (URL) |
За вмістом (хеш) |
| Залежність від серверів |
Висока |
Низька |
| Доступність |
Залежить від одного джерела |
Розподілена між багатьма вузлами |
| Безпека |
Уразливий до підробок |
Криптографічний контроль |
| Цензура |
Можлива |
Практично неможлива |
Як почати використовувати IPFS?
- Встановіть IPFS-клієнт:
- Завантажте та встановіть IPFS-клієнт з офіційного сайту (наприклад, IPFS Desktop або IPFS CLI).
- Запустіть вузол:
- Після встановлення ви можете підключитися до мережі IPFS та почати зберігати або отримувати файли.
- Додайте файл до IPFS:
- Використовуйте команду
ipfs add <назва_файлу> для додавання файлу до мережі. Ви отримаєте унікальний хеш, який представляє цей файл.
- Отримайте файл:
- Інші користувачі можуть отримати файл за його хешем, використовуючи команду
ipfs cat <хеш>.
- Використовуйте IPFS Gateway:
- Для доступу до IPFS-даних через браузер використовуйте шлюзи (наприклад, https://ipfs.io).
Виклики та обмеження IPFS
- Масштабованість:
- Розподілене зберігання вимагає значних обсягів пам’яті та обчислювальних ресурсів.
- Час доступу:
- Через мережеві затримки час доступу до деяких даних може бути більшим, ніж у традиційній моделі.
- Приватність:
- Дані в IPFS доступні всім користувачам, якщо вони не шифруються перед завантаженням.
- Інтеграція:
- IPFS ще не є стандартом для вебу, тому інтеграція може бути складною.
Майбутнє IPFS
IPFS має потенціал змінити спосіб зберігання і передачі даних в інтернеті. З розвитком технологій блокчейну та децентралізованих додатків (DApps), роль IPFS як основного протоколу передачі файлів може значно зрости. У майбутньому його використання може поширитися на такі сфери, як:
- Електронне врядування.
- Освіта.
- Медичні записи.
IPFS — це не просто інновація, а крок до децентралізованого інтернету, який буде більш відкритим, безпечним та стійким до зовнішніх впливів.
Порівняння GitLab Cache та GitLab Artifacts

GitLab є потужним інструментом для управління репозиторіями та організації CI/CD-процесів. У його функціоналі є два важливі елементи — GitLab Cache та GitLab Artifacts. Хоча вони можуть здатися схожими, їх призначення, спосіб використання та механізми роботи мають суттєві відмінності. У цій статті ми детально розглянемо, що таке GitLab Cache і GitLab Artifacts, у чому їхня різниця та як ефективно їх використовувати у ваших CI/CD-проектах.
Що таке GitLab Cache?
GitLab Cache (кеш) — це механізм тимчасового зберігання даних між різними джобами або пайплайнами. Кеш призначений для прискорення виконання джобів, зберігаючи залежності або тимчасові файли, які повторно використовуються в межах одного проекту.
Основні характеристики GitLab Cache
- Призначення: Прискорення процесу виконання CI/CD джобів за рахунок повторного використання даних.
- Приклади використання:
- Зберігання залежностей (наприклад, файлів
node_modules для Node.js чи vendor для PHP).
- Кешування результатів компіляції для зменшення часу збірки.
- Час зберігання: Конфігурація кешу дозволяє налаштувати час його існування (
expire_in), після чого кеш буде автоматично видалено.
- Місце зберігання: Кеш зберігається на виконавчому середовищі (runner).
Конфігурація GitLab Cache
Для налаштування кешу використовується ключ cache у файлі .gitlab-ci.yml.
Приклад:
cache:
key: "node_modules"
paths:
- node_modules/
policy: pull-push
expire_in: 1 week
key: Унікальний ключ для кешу.
paths: Шляхи до файлів або папок, які потрібно закешувати.
policy: Політика використання кешу (pull, push, pull-push).
expire_in: Тривалість зберігання кешу.
Що таке GitLab Artifacts?
GitLab Artifacts (артефакти) — це результат виконання джобу, який передається для подальшого використання в інших джобах або для аналізу.
Основні характеристики GitLab Artifacts
- Призначення: Збереження результатів виконання джобів, таких як зібрані файли, звіти про тести, артефакти збірки.
- Приклади використання:
- Передача файлів збірки між джобами.
- Зберігання логів тестів або звітів у форматі HTML.
- Розповсюдження зібраного коду для подальшого використання.
- Час зберігання: Артефакти можна зберігати тимчасово або постійно (за замовчуванням — 30 днів).
- Місце зберігання: Артефакти зберігаються на сервері GitLab.
Конфігурація GitLab Artifacts
Для налаштування артефактів використовується ключ artifacts у файлі .gitlab-ci.yml.
Приклад:
artifacts:
paths:
- dist/
expire_in: 1 week
reports:
junit: test-results.xml
paths: Шляхи до файлів або папок, які слід зберегти як артефакти.
expire_in: Тривалість зберігання артефактів.
reports: Спеціалізовані звіти (наприклад, JUnit або Code Quality).
Основні відмінності між GitLab Cache та GitLab Artifacts
| Характеристика |
GitLab Cache |
GitLab Artifacts |
| Призначення |
Прискорення виконання джобів |
Збереження та передача результатів виконання джобів |
| Область використання |
Залежності, тимчасові файли |
Результати збірки, тести, логи |
| Місце зберігання |
Виконавче середовище (runner) |
Сервер GitLab |
| Час зберігання |
Налаштовується через expire_in |
Налаштовується через expire_in |
| Політика збереження |
Тимчасове зберігання |
Тимчасове або постійне зберігання |
| Передача між джобами |
Не призначений для передачі |
Використовується для передачі між джобами |
| Підтримка звітів |
Ні |
Так (JUnit, Code Quality, Security Reports) |
Як вибрати між GitLab Cache та GitLab Artifacts
Використовуйте GitLab Cache, якщо:
- Ви хочете прискорити процес збірки за рахунок повторного використання залежностей.
- Потрібно кешувати файли, які не є результатом кінцевої збірки.
- Дані будуть використовуватися лише в рамках поточного проекту.
Приклад: Кешування залежностей у Node.js проекті:
cache:
paths:
- node_modules/
Використовуйте GitLab Artifacts, якщо:
- Ви хочете передати результати виконання джобів для використання іншими джобами.
- Потрібно зберегти зібрані файли, тести або логи для аналізу.
- Потрібен доступ до результатів через вебінтерфейс GitLab.
Приклад: Передача зібраного коду для наступної джоби:
artifacts:
paths:
- dist/
Як поєднати GitLab Cache та GitLab Artifacts
У складних CI/CD-пайплайнах можна одночасно використовувати GitLab Cache і GitLab Artifacts для досягнення оптимальних результатів.
Приклад:
stages:
- install
- build
- test
install:
stage: install
script:
- npm install
cache:
paths:
- node_modules/
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
test:
stage: test
script:
- npm test
artifacts:
reports:
junit: test-results.xml
У цьому прикладі:
- Кеш використовується для збереження залежностей.
- Артефакти зберігають результати збірки та звіти тестів.
Висновок
GitLab Cache і GitLab Artifacts виконують різні ролі в CI/CD-процесах. Cache забезпечує повторне використання даних для пришвидшення джобів, тоді як Artifacts дозволяє передавати результати виконання між джобами та зберігати їх для подальшого аналізу. Розуміння їхніх особливостей та правильне використання допоможе вам створити ефективні та оптимізовані CI/CD-пайплайни у ваших проектах.
Як працювати з потоками JavaScript: оптимізація асинхронних запитів

Асинхронна робота з потоками даних є важливою складовою сучасного програмування в JavaScript. З огляду на зростання обсягу даних і складність додатків, оптимізація асинхронних запитів стала необхідністю для забезпечення швидкої та ефективної роботи програм. У цій статті розглянемо концепцію потоків, їхнє використання та методи оптимізації асинхронних запитів у JavaScript.
Основи потоків у JavaScript
Що таке потоки?
Потоки в JavaScript — це абстракція для роботи з потоковими даними, які надходять поступово, а не всі одразу. Це можуть бути файли, мережеві дані, або навіть дані, що генеруються в реальному часі.
JavaScript реалізує роботу з потоками через Streams API, яка включає:
- Readable Streams (читабельні потоки): для читання даних.
- Writable Streams (записувані потоки): для запису даних.
- Transform Streams (трансформуючі потоки): для обробки даних між читанням і записом.
Асинхронність у потоках
Асинхронність — це фундаментальний принцип роботи з потоками в JavaScript. Для її реалізації використовується механізм Promises і синтаксис async/await. Це дозволяє обробляти дані по мірі їхнього надходження без блокування основного потоку виконання.
Приклад читання даних із потоку:
const reader = stream.getReader();
async function readStream() {
let done = false;
while (!done) {
const { value, done: streamDone } = await reader.read();
done = streamDone;
if (value) {
console.log(value);
}
}
}
readStream();
Як працювати з асинхронними запитами
Асинхронні запити є основою взаємодії з API або зовнішніми ресурсами. Вони використовують fetch, XMLHttpRequest чи сторонні бібліотеки, такі як Axios.
Приклад асинхронного запиту з fetch:
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData('https://api.example.com/data');
Проблеми асинхронних запитів
1. Перевантаження сервера
Надмірна кількість запитів може призвести до перевантаження серверів і збільшення часу відповіді.
2. Некоректна обробка помилок
Без належної обробки помилок додаток може припинити свою роботу через одну невдалу відповідь.
3. Витрати ресурсів
Асинхронні запити споживають системні ресурси, і неефективне управління ними може призвести до низької продуктивності.
Оптимізація асинхронних запитів
1. Використання пулу запитів
Щоб уникнути перевантаження сервера, використовуйте пул запитів. Це означає, що ви можете обмежити кількість одночасно виконуваних запитів.
Приклад:
async function fetchWithLimit(urls, limit) {
const results = [];
const executing = [];
for (const url of urls) {
const promise = fetch(url).then(res => res.json());
results.push(promise);
if (executing.length >= limit) {
await Promise.race(executing);
}
executing.push(promise);
promise.finally(() => executing.splice(executing.indexOf(promise), 1));
}
return Promise.all(results);
}
fetchWithLimit(['https://api.example.com/data1', 'https://api.example.com/data2'], 2);
2. Кешування результатів
Кешування дозволяє уникнути повторного виконання тих самих запитів.
Приклад:
const cache = new Map();
async function fetchWithCache(url) {
if (cache.has(url)) {
return cache.get(url);
}
const response = await fetch(url);
const data = await response.json();
cache.set(url, data);
return data;
}
fetchWithCache('https://api.example.com/data');
3. Дедуплікація запитів
Якщо один і той самий запит виконується кілька разів одночасно, це може створити надлишкове навантаження. Для цього використовуйте механізми дедуплікації.
Приклад:
const inFlightRequests = new Map();
async function fetchOnce(url) {
if (inFlightRequests.has(url)) {
return inFlightRequests.get(url);
}
const promise = fetch(url).then(res => res.json());
inFlightRequests.set(url, promise);
try {
return await promise;
} finally {
inFlightRequests.delete(url);
}
}
fetchOnce('https://api.example.com/data');
4. Паралельна обробка з Promise.all
Якщо запити не залежать один від одного, їх можна виконувати паралельно.
Приклад:
async function fetchParallel(urls) {
const promises = urls.map(url => fetch(url).then(res => res.json()));
return Promise.all(promises);
}
fetchParallel(['https://api.example.com/data1', 'https://api.example.com/data2']);
5. Ліміт часу запиту
Для уникнення зависання запиту можна встановити тайм-аут.
Приклад:
async function fetchWithTimeout(url, timeout) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} catch (error) {
console.error('Request timed out:', error);
} finally {
clearTimeout(id);
}
}
fetchWithTimeout('https://api.example.com/data', 5000);
Висновок
Потоки JavaScript і асинхронні запити є важливими інструментами для створення сучасних вебдодатків. Однак їхнє неефективне використання може призвести до проблем продуктивності. Оптимізація, така як використання пулів запитів, кешування, дедуплікація, та обробка помилок, допомагає забезпечити стабільну й ефективну роботу ваших додатків. Ретельно тестуйте та впроваджуйте ці підходи, щоб підвищити якість взаємодії з вашими користувачами.
HTML та CSS помилки, що впливають на доступність

Доступність вебсайтів є важливою складовою сучасного веброзроблення. Вона гарантує, що ресурси можуть бути використані всіма людьми, включно з тими, хто має обмежені можливості. Однак, недоліки у написанні HTML та CSS часто призводять до проблем із доступністю. У цій статті розглянемо найпоширеніші помилки та способи їх уникнення.
Основні HTML-помилки
1. Відсутність текстових альтернатив для зображень
Зображення без альтернативного тексту (атрибута alt) стають недоступними для людей із вадами зору, які використовують екранні зчитувачі. Атрибут alt надає короткий опис зображення, який допомагає користувачам зрозуміти його зміст.
Помилка:
<img src="example.jpg">
Правильний підхід:
<img src="example.jpg" alt="Опис зображення">
2. Неправильне використання заголовків
Заголовки (<h1> до <h6>) повинні використовуватися ієрархічно, щоб користувачі могли легко орієнтуватися на сторінці. Пропуск рівнів (наприклад, <h1> одразу за <h3>) порушує логіку документа.
Помилка:
<h1>Основний заголовок</h1>
<h3>Розділ</h3>
Правильний підхід:
<h1>Основний заголовок</h1>
<h2>Розділ</h2>
3. Відсутність опису для форм
Форми без міток (label) ускладнюють взаємодію для людей із вадами зору. Поля форми повинні мати зрозумілий опис.
Помилка:
<input type="text" placeholder="Ваше ім'я">
Правильний підхід:
<label for="name">Ваше ім'я</label>
<input type="text" id="name">
4. Використання таблиць для розташування контенту
Таблиці повинні використовуватися тільки для табличних даних, а не для створення макетів. Це збільшує складність для екранних зчитувачів.
Помилка:
<table>
<tr>
<td>Контент</td>
<td>Ще контент</td>
</tr>
</table>
Правильний підхід: Використовуйте CSS для верстки замість таблиць:
<div class="container">
<div>Контент</div>
<div>Ще контент</div>
</div>
5. Проблеми з фокусом
Інтерактивні елементи, такі як кнопки чи посилання, мають бути доступними за допомогою клавіатури. Якщо фокус не працює належним чином, це може стати серйозною перешкодою для користувачів.
Помилка:
<button onclick="doSomething()">Натисніть</button>
Правильний підхід: Переконайтеся, що кнопка фокусується:
<button onclick="doSomething()" tabindex="0">Натисніть</button>
Основні CSS-помилки
1. Недостатній контраст тексту
Користувачі з порушеннями зору можуть не побачити текст із низьким контрастом.
Помилка:
body {
color: #999;
background-color: #fff;
}
Правильний підхід:
body {
color: #000;
background-color: #fff;
}
Рекомендується використовувати інструменти для перевірки контрасту, наприклад, WebAIM Contrast Checker.
2. Використання лише кольорів для передачі інформації
Користувачі, які не розрізняють кольори, не зможуть зрозуміти інформацію, що залежить від кольору.
Помилка:
<p style="color: red;">Помилка</p>
Правильний підхід:
<p style="color: red;">Помилка <span class="icon-error" aria-hidden="true">❌</span></p>
3. Відключення фокуса через CSS
Видалення контурів фокуса ускладнює навігацію клавіатурою.
Помилка:
button:focus {
outline: none;
}
Правильний підхід:
button:focus {
outline: 2px solid blue;
}
4. Фіксовані розміри елементів
Встановлення фіксованих розмірів елементів може спричинити проблеми на різних пристроях.
Помилка:
div {
width: 500px;
height: 300px;
}
Правильний підхід:
div {
max-width: 100%;
height: auto;
}
5. Неправильне розташування елементів
Неправильне розташування елементів за допомогою absolute чи fixed без урахування адаптивності може порушити порядок читання для екранних зчитувачів.
Помилка:
div {
position: absolute;
top: 50px;
left: 100px;
}
Правильний підхід: Використовуйте адаптивні підходи:
div {
position: relative;
margin: 20px auto;
}
Як уникнути помилок
- Тестуйте доступність. Використовуйте інструменти, такі як Lighthouse чи Axe, для аналізу доступності вашого сайту.
- Дотримуйтеся стандартів. Переконайтеся, що ваш код відповідає рекомендаціям WCAG (Web Content Accessibility Guidelines).
- Покращуйте семантику. Використовуйте семантичні елементи HTML для структурування контенту.
- Спілкуйтеся з користувачами. Запитуйте зворотний зв’язок від людей із різними потребами.
Висновок
HTML і CSS відіграють важливу роль у створенні доступних вебсайтів. Уникнення помилок, описаних у цій статті, дозволить зробити ваш ресурс більш зручним для всіх користувачів. Дотримання стандартів доступності — це не лише технічна необхідність, а й важливий крок до інклюзивності.
Що таке NFT?

NFT (невзаємозамінні токени, від англ. Non-Fungible Tokens) — це цифрові активи, які є унікальними та неповторними. Вони засновані на технології блокчейну і забезпечують право власності на об’єкти криптографічних токенів. Складніше за своєю суттю ніж криптовалюти, NFT створюють цифровий світ, де кожен об’єкт є унікальним.
Основи NFT
Що означає “невзаємозамінність”?
У фінансах замінні активи можна вільно обмінювати між собою. Наприклад, 1 биткоїн однаковий з іншим биткоїном. Невзаємозамінні активи унікальні і не можуть бути однаковими з іншими. Кожний NFT має свій унікальний код.
Як працюють NFT?
NFT функціонують на блокчейнах, таких як Ethereum, Polygon або Solana. Вони використовують смарт-контракти, які забезпечують автоматизоване виконання умов угод.
- Кожен NFT є унікальним. Запис про нього записується у блокчейні і забезпечується криптографією.
- Підтвердження власності. Тільки той, хто має приватний ключ від NFT, є його справжнім власником.
- Можливість перепродажу. NFT можна передавати чи продавати, що дозволяє створювати вторинний ринок.
Приклади використання NFT
Мистецтво
NFT стали популярними серед художників. Завдяки блокчейну автори можуть продавати свої роботи без посередників, отримуючи роялті за кожну наступну перепродажу. Наприклад, колекція Beeple була продана за понад $69 мільйонів на аукціоні.
Ігрова індустрія
У відеоіграх NFT використовуються для створення внутрішньоігрових активів, які гравці можуть купувати, продавати чи обмінювати. Це додає додаткову цінність грі, оскільки активи стають справжньою власністю гравців.
Колекціонування
NFT відкривають нові можливості для цифрового колекціонування. Відомі бренди, такі як NBA, створюють колекції цифрових карток, які можна зберігати або обмінювати.
Музика
Музиканти використовують NFT для продажу альбомів, квитків на концерти чи навіть ексклюзивного контенту, доступного лише власникам токенів.
Нерухомість
NFT знаходять застосування у віртуальній нерухомості. Платформи, такі як Decentraland або The Sandbox, дозволяють купувати, продавати й будувати на віртуальних землях.
Переваги NFT
- Прозорість. Усі транзакції записуються у блокчейні, що забезпечує прозорість і відсутність шахрайства.
- Додатковий дохід. Художники, музиканти й творці контенту можуть отримувати роялті за кожну перепродажу їхніх NFT.
- Цифрова унікальність. Кожен NFT — це унікальний цифровий актив із підтвердженням права власності.
Виклики NFT
- Волатильність. Ціна на NFT може різко змінюватися, що робить інвестиції ризикованими.
- Екологічний вплив. Деякі блокчейни споживають багато енергії, що викликає екологічні занепокоєння.
- Юридичні питання. Регуляторна база для NFT поки що недостатньо розвинена.
Як створити NFT
- Вибір блокчейну. Найпопулярнішими платформами є Ethereum, Binance Smart Chain, Solana.
- Налаштування гаманця. Створіть криптогаманець, наприклад MetaMask.
- Мінтинг. Використовуйте платформи, такі як OpenSea чи Rarible, щоб створити NFT, завантаживши цифровий файл (зображення, аудіо тощо).
- Продаж. Виставте NFT на продаж на маркетплейсі.
Майбутнє NFT
NFT мають потенціал змінити багато галузей, роблячи власність більш прозорою та ефективною. У майбутньому очікується розширення сфер використання NFT, зокрема в освіті, юриспруденції та охороні здоров’я. Цифрові дипломи, сертифікати й ліцензії можуть бути переведені в NFT для спрощення перевірки та підвищення довіри.
Нові галузі застосування
- Освіта. Дипломи й сертифікати можна оцифрувати у вигляді NFT, що дозволить роботодавцям швидко перевіряти автентичність документів.
- Охорона здоров’я. Медичні записи можуть зберігатися в NFT-форматі, що забезпечить безпеку даних і зручність доступу для пацієнтів і лікарів.
- Юридичні послуги. Контракти, підписані у вигляді NFT, можуть автоматично виконуватися завдяки смарт-контрактам.
Використання в реальному світі
Популярність NFT також зростає в індустрії подорожей та розваг. NFT-квитки можуть стати стандартом у майбутньому для концертів, подій і транспортних послуг, дозволяючи боротися з підробками і перепродажами за спекулятивними цінами.
NFT — це більше, ніж просто цифрові зображення чи ігрові предмети. Це інструмент, який може змінити багато аспектів нашого життя, роблячи їх більш прозорими, безпечними та ефективними. Хоча перед цією технологією стоять виклики, її потенціал важко переоцінити.