Free React For Beginners
3.46K subscribers
231 photos
5 videos
1 file
385 links
💻 Про #React та #frontend та #веб розробку
🧑‍🎓 Для початківців і не тільки

👉 https://www.youtube.com/@reactdev
Download Telegram
Не популярні, але корисні хуки в React (1/3)

const inputId = useId();

Використовується в динамічних формах для зв'язки input та label, а також в компоненті врапері для label+input якщо ви не хочете прокидувати id як пропс. Безпечний для SSR.

const inputId = useId();
return <>
<label htmlFor={inputId}>Hello</label>
<input id={inputId}/>
</>


Деталі: ключ не випадковий, має вигляд :rX: де X просто глобальний counter в React. Якщо (випадково) у вас 2+ реакт застосунків на сторінці - використовуйте identifierPrefix, який передається при ініціалізації React застосунку

Сторонній ефект: Автоматизатори, які покаладються на id елементів вас не люблять. А все тому що треба користуватися data-test-id, а не лізти куди не просять.

Документація


@reactbeginners
👍489🔥3
Не популярні корисні хуки в React (2/3)

const deferedValue = useDeferredValue(value);

Використовується, коли ви хочете мати можливість відкласти оновлення якогось компоненту на "трошечки потім", наприклад під час роботи з мишкою або мережевими запитами

const [point, setPoint] = useState({ x: 0, y: 0 });
const deferedPoint = useDeferredValue(point);
return (
<>
<div
style={{ height: `50vh` }}
onMouseMove={(e) => setPoint({ x: e.screenX, y: e.screenY })}
></div>
<SomeComponent point={deferedPoint} />
</>
);


Деталі: Значення deferedValue змінюється із невеликою затримкою, проміжні значення з'їдаються, а компонент отримує останнє значення. Відповідно ви зможете зеконимити на рендері дочірніх компонентів. Для цього потрібно реалізувати PureComponent або огорнути дочірній компонент в React.memo. Окрім цього, компонент який працює з deferedValue "не підвисає", оскільки React вміє відміняти рендери, викликані оновленням deferedValue

Cторонній ефект: це оптимізація швидкодії яка трохи ускладнює код, використовувати разом із вимірюванням.

@reactbeginners
👍609❤‍🔥2
Не популярні корисні хуки в React (3/3)

Не дам, поки перші два не полайкаєте! Для кого я їх писав?

Насправді, оскільки довелося перевіряти деяки речі, то й сам дізнався цікаві моменти. Наприклад я вважав що useId видає унікальний айдішник (а це не так)

Оновлено: ніт, я не жлоб)
😁31👍2
Третій хук може й не популярний, але смачний як вафельний торт зі згущеним молоком. Але й складний, нажаль. Можливо тому й не популярний.

Все, зараз буде, налайкали)
🔥23
Не популярні корисні хуки в React (3/3)

const userName = useSyncExternalStore(
userStore.subscribe,
() => userStore.userName
);


❤️Можливість мати стор окремо від компоненту без зайвих бібліотек (топ штука, але вже пізно)❤️

function UserEditor() {
const userName = useSyncExternalStore(
userStore.subscribe,
() => userStore.userName
);
return (
<>
<h1>Hello {userName}</h1>
<input onChange={(e) => userStore.setUserName(e.target.value)} />
</>
);
}



class ExternalStore {
private _listeners: (() => void)[] = [];
constructor(private readonly _user: User) {}

get userName() {
return this._user.name;
}

setUserName = (name: string) => {
this._user.name = name;
this._listeners.forEach((l) => l());
};

subscribe = (listener: () => void) => {
this._listeners.push(listener);
return () => (this._listeners = this._listeners.filter(listener));
};
}


Деталі: Хук дозволяє підписатися на зміни в об'єктах, які знаходиться поза межами React. Два важливі моменти: 1) Функція subscribe зобов'язана повертати функцію відписки. 2) Функція, яка отримує дані, має повертати нові значення виключно якщо ті були змінені. Повернення НОВОГО об'єкту на кожен виклик призведе до помилки.

Сторонній ефект: На вас будуть дивно дивитися, бо це ж не канонічно.
Документація

@reactbeginners
👍175🔥3
Free React For Beginners
Не популярні корисні хуки в React (3/3) const userName = useSyncExternalStore( userStore.subscribe, () => userStore.userName ); ❤️Можливість мати стор окремо від компоненту без зайвих бібліотек (топ штука, але вже пізно)❤️ function UserEditor() { …
От ви мені зараз не вірите, а це, концептуально, просто найкрутіший хук з усіх. 💪💪💪

Він дозволяє повністю відокремити ваш стейт від React взагалі. Тестувати стає набагато простіше, логіка лежить окремо від UI. Якщо захочете, зможете навіть UI поміняти без шкоди для логіки. Це дуже крута штука, яка, до того ж, не потребує жодних сторонніх бібліотек і є просто з коробки! Якби ж вона була від самого початку, було б набагато простіше. 😢

Про експерементальні хуки писати?
👍222
👉 Ось туточки в лінкедині всі хуки в одному місці у формі презентації (нажаль зібрати їх докупи в Telegram не вийде)

Якщо корисно, додавайте до обраного, ставте там все що треба і так далі)

Сподіваюся зміг вам сьогодні принести щось і корисне і цікаве. Ще на цьому тижні буде "народний проект", так що чекайте на анонс.

Чим більше реакцій від вас тим більше контенту)

Пішов працювати. Next-е, я іду...
👍203
Будуть розбирати резюме, не моє 😁. Жарти жартами, а резюме треба((
Хуки канарки

Як ви знаєте, поточна версія React - 18.2 і вона не оновлювалася десь два роки. Але окрім цієї стабільно-застійної версії, React постійно випускає канаркові релізи. Вони вважаються "умовно" стабільними. Власне, Next.JS використовує саме ці релізи, про що я перекладав статтю раніше (тиць)

І ось там, у канарковому релізі, є декілька нових хуків один з яких може бути цікавим:

В самому React-і додалися два нових хуки:

1. Хук use, який інтегрований з компонентом Suspense і який дозволяє працювати напряму з Promise та з контекстом

2. Хук useOptimistic, який нам має допомогти з показом "оптимістичного"\* результату асинхронних операцій

А ще два хуки були додані в React-dom: useFormStatus та useFormState, але з ними без чашки кави так просто не розібратися.

От про перший ми завтра і поговоримо, бо я сам тільки з навчання і ледь доплентався додому.

* Оптимістичний апдейт - це коли ми повідомляємо користувачеві про успішність операції, не маючи на це підтвердження.

Всім тихого вечора
👍201
Народний проект, частина друга - четвер, 19:00, YouTube

🍹Поки є умовно вільні вечори - пропоную продовжити "Народний проект" - проект на React який робиться повністю в прямому ефірі.

📅 Кому цікаво - приєднуйтесь завтра о 19:00. В планах використати хук useSyncExternalStore та задеплоїти проект на GitHub pages.

Кому не цікаво - сьогодні буде пост про хук use

@reactbeginners
❤‍🔥17👍7🍾1
Про новий хук `use`

Хук дозволяє вам працювати з промісами так, наче це звичайні значення:

const user = use(Promise.resolve({ name: 'Vitalii' }));
return <>{user.name}</>;


Більше того, це єдиний хук який можна використовувати умовно, в тому числі в тернаних операторах:

if (!userId) return <>User not found</>;
const user = use(Promise.resolve({ name: 'Vitalii' }));
return <>{user.name}</>;


Хук use також можна використати для отримання контексту. Різниця між use та useContext полягає в тому, що useContext не можна використовувати умовно. А use можна.

Ось так просто це виглядає. Але є кілька нюансів, які ще й відрізняються в залежності від того чи це чистий React чи Next.

Про React

1. Use не доступний в React 18.2. Для того щоб його використати потрібно встановити react@canary версію, про це буде окремо.
2. Для того аби цей хук працював як очікувано, компонент в якому використаний хук use має бути огорнуто в компонент Suspense, який також показує індикацію завантаження
3. На версії 18.3.0-canary-247738465-20240130, ErrorBoundaries з rejected promise не працюють, хоча мають.

Про Next.JS (дожились, да?)

1. Use доступний в останній версії Next. Встановлювати щось додаткове не потрібно.
2. Хук працює лише в серверних компонентах (чому??), але не потребує використання Suspense
3. Для індикації завантаження можна використовувати файл loading.tsx
4. Для відображення помилки можна використовувати компонент error.tsx

Але в серверних компонентах можна використовувати async/await що виглядає простіше.

В підсумку - на мене виглядає все "дуже цікаво", але або недопрацьовано (react), або недопрацьовано і безтолково (next). Але це моя особиста думка.

@reactbeginners
9👍42
Free React For Beginners
А хто не розуміє навіщо цей хук потрібен? (за умови що він ідеально працює) поставте ❤️
Ок, тоді давайте розбиратися на прикладах, буде трохи тексту, але ви самі хотіли.
10
1) Ось приклад найпростішого! компоненту, якому потрібно отримати асинхронні дані

function UserDetails() {
const [user, setUser] = useState({
loading: false,
data: null,
error: null,
});

useEffect(() => {
setUser({ ...user, loading: true });
fetchUser()
.then((user) =>
setUser({ data: user, error: null, loading: false })
)
.catch((error) =>
setUser({ data: null, loading: false, error })
);
}, []);

if (user.loading) {
return <>loading</>;
}

if (user.error) {
return <>Something went wrong</>;
}

return <>{user.data.name}</>;
}


Як бачите, навіть незважаючи на те, що функціональність у нього мінімальна, він містить забагато всього:

1. Отримує дані
2. Керує індикацією завантаження
3. Відображає індикацію завантаження
4. Керує роботою з помилками
5. Відображає помилку
6. Відображає користувача.

Наш UserDetails забагато знає. Це призводить до того, що, у випадку будь-якої зміни цих пунктів, вам доведеться чіпати компонент UserDetails, що робить його крихким. Окрім цього це просто більше коду який складніше читати, а використання ефекту лише погіршує ситуацію, оскільки тепер ми не можемо читати код згори вниз, нам потрібно пам'ятати, що спочатку код виконається без ефекту, потім спрацює ефект і код виконається повторно з оновленим станом.

Окрім цього, коли вам знадобиться отримати інші асинхронні дані, ви будете змушені повторити цей самий код, разом зі стейтом, ефектом та двома if-ами. Це дублювання коду, робити це ніхто не хоче.

Також є друга проблема - наш компонент все ще занадто обізнаний речами які його хвилювати не мають - він знає про те, який компонент відображає помилку, а який відображає завантаження, це теж погано.

Тепер давайте подивимось на приклад ідеального use (хоча б useAsync його назвали, не знаю)

@reactbeginners
❤‍🔥8
2) А ось такий самий приклад з використання хуку use

function UserDetails() {
const user = use(fetchUser());
return <>{user.name}</>;
}

<ErrorBoundaries error={<>Something went wrong</>}>
<Suspense fallback={<>loading</>}>
<UserDetails />
</Suspense>
</ErrorBoundaries>;


Просто порівняйте два компоненти:

1. Читати компонент UserDetails стало набагато простіше.
2. Він зайнятий виключно тим чим потрібно - відмальовує нашого користувача
3. Коли нам знадобиться змінити лоадер - ми будемо змінювати лише компонент лоадер. Коли нам буде потрібно оновити компонент з помилкою, ми також оновимо лише його. Це гарантує що ми не зламаємо наш компонент UserDetails і рев'ювати такі зміні набагато приємніше.
4. Перевикористовувати код стало простіше, а кастомний хук більше не потрібен.


Єдиний тут "недолік", що ErrorBoundaries вам таки доведеться один раз зробити самому.

А тепер скажіть мені - який код вам легше читати та підтримувати?

@reactbeginners
16
Але назва хуку, те що він тепер вміє працювати одразу і з контекстом і з асинхронними даними - це лажа з лаж.

Чого?

Бо це теж порушення separation of concerns 😁
👍6
Інструкція, як встановити канаркову версію React


npm init vite react-canary
cd react-canary
npm i
npm i react@18.3.0-canary-247738465-20240130 react-dom@18.3.0-canary-247738465-20240130


Якщо використовуєте TypeScript, потрібно оновити секцію compilerOptions в tsConfig.json та додати типи: "types": [ "react/canary", "react-dom/canary" ]

Канарковий реліз відкриває доступ до:

1. import { use } from 'react'
2. import { useOptimistic } from 'react'
3. import { useFormStatus } from 'react-dom'
4. import { useFormState } from 'react-dom'
5. 'use client'
6. 'use server'
7. form🤯
8. cache

І так, це не контент для початківців. Але маємо рости і будемо рости.

@reactbeginners
👍13
Щось я злий і не виспаний... Ще й з тасками налажали. 😤

Зате хоч грілки вже забрали і навіть фото скинули. Сьогодні зроблю вам звіт що купили, почому і скільки грошей лишилося.

Бережіть себе і висипайтеся за можливості.
25👍6
Підсумки по збору на грілки

Зібрано:
Банка: 9000 грн
ПБ: 300 грн
Попередній залишок: 16грн
Сума: 9316

Придбано:
Грілки для ніг HeatPaxx, 8 годин, 160 шт. по 30 грн
Грілки для рук ThermoPaxx, 10 годин, 116 штук по 30 гривень.
Доставка 265 гривень, адресна.

Сума: 8545 гривень.


Залишок: 9316 - 8545 = 771 (тепер є банка де ви можете бачите всі залишки)

Takehot на той момент закінчилися, а їх грілка для ніг в моєму кармані пропрацювала 2 години.

Розглядався варіант з Декатлоном, але ті що ми взяли були перевірені, а Декатлон ні.

Якщо не буде заперечень, залишок відправлю на збір на машину одному підрозділу, про них буде трохи пізніше.

Дякую всім хто долучився, ми зробили маленьку, але дуже корисну справу, ви це самі розумієте.

На наступний збір знайду вам щось гарне на розіграш. Може книжку? Чи мерч?

Бережіть себе і допомагайте ЗСУ та один одному.
👍1910