ch
Feedback
Free React For Beginners

Free React For Beginners

前往频道在 Telegram

💻 Про #React та #frontend та #веб розробку 🧑‍🎓 Для початківців і не тільки 👉 https://www.youtube.com/@reactdev

显示更多
3 232
订阅者
无数据24 小时
-47
-2130
帖子存档
В скарбничку багів та дитячих хвороб Next.JS на page* роутері Маємо дуже простий React код:
const { query } = useRouter();
return <>{query.id ? 'HELLO': 'ERROR'}</>
Звичайними словами - якщо в URL є id з якимось значенням - виведи HELLO, якщо немає - виведи ERROR Тепер питання, що буде виведено на екран протягом наступної секунди, якщо ваш користувач зайде на URL: /?id=test Спочатку дайте відповідь собі і напишіть у коментарях, а потім заглядайте: Спочатку виведеться ERROR Потім екран оновиться і виведеться HELLO Це відбувається тому, що в Next.JS router має ще один прапорець - `isReady`, який потрібно перевіряти перед тим як звертатися до роутера. Поки він не ready - там може не бути тих значень на які ви очікуєте. І це відбувається незважаючи на те, що URL та всі дані в ньому вже існують під час обробки запиту на сервері. * На щастя, в новому app роутері цю проблему вже вирішили. Для цього знадобилося усього 13 мажорних релізів :)

Ранок видався відверто паршивим. Сподіваюся усі цілі (

Якщо вам сумно постійно писати обробку помилок ви завжди можете написати універсальний компонент: Для цього потрібно створити класовий компонент (функціональні такого не вміють) в якому реалізувати три методи: getDerivedStateFromError - оновлює ваш стейт у випадку перехоплення помилки componentDidCatch - перехоплює помилку і може щось із нею зробити (залогувати, наприклад) render - відображає контент в залежності від того чи була помилка, чи ні. В коді це виглядає так:
class SimpleErrorBoundaries extends PureComponent<
  SimpleErrorBoundariesProps,
  SimpleErrorBoundariesState
> {
  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error };
  }

  state = { hasError: false };

  render() {
    const { children, errorFallback } = this.props;
    return this.state.hasError ? errorFallback : children;
  }

  componentDidCatch(error: Error): void {
    this.props.onError && this.props.onError(error);
  }
}

Типи виглядають досить просто
type SimpleErrorBoundariesProps = {
  children: ReactNode;
  errorFallback: ReactNode;
  onError?: (error: Error) => void;
};

type SimpleErrorBoundariesState =
  | { hasError: false }
  | { hasError: true; error: Error };
Тепер ви можете писати код накшталт такого:
<SimpleErrorBoundaries errorFallback={<>Sorry mate</>}>
  <ErrorComponent />
</SimpleErrorBoundaries>
❗️Варто пам'ятати 1 . Виключення, які стаються в середині промісів просто так не перехоплюються, для цього потрібно використовувати async/await 2. Виключення, що стаються в середині самого компоненту ErrorBoundaries також не перехоплюються. Для обробки помилок в Next.JS цей підхід також працює. Але, як ще один варіант, ви можете використати файл error.tsx дефолтний експорт якого буде відображений у випадку, якщо в роуті станеться помилка. @reactbeginners

Обіцяв я вам сюрприз сьогодні - ось маєте Відео № 1 - Вступ до курсу Next.JS Відео № 2 - Що таке Next.JS Буду потрохи викладати, тому що статися може що завгодно, хай краще залишиться незакінченим ніж лежатиме у приватних. Всім дякую!

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

❓Як відмінити мережевий запит в React Тут в LinkedIn пролетіло питання - як відмінити мережевий запит в React. На щастя все с
Як відмінити мережевий запит в React Тут в LinkedIn пролетіло питання - як відмінити мережевий запит в React. На щастя все стало досить просто після появи спеціального класу AbortController. Виглядає це щастя ось так:
useEffect(() => {
  // Створюємо екземпляр AbortController
  const abortController = new AbortController();

  // Робимо запит та передаємо у fetch `signal'
  // Цей сигнал "просигналить" фетчу, 
  // якщо виникне необхідність відміни запиту
  fetch('/user', {signal: abortController.signal});

  // Повертаємо функцію відписки з  ефекту
  // Ця функція буде викликана коли компонент буде видалений
  // Або зміняться його залежності
  // І викличе сигнал, який повідомить фетчу про відміну
  return () => abortController.abort();
}, []);
Як бачите - не складно. Якщо ви працюєте з axios - все те саме, також через AbortController Cподіваюся було корисно. @reactbeginners

І продовжуючи тему фронтенду, хто не знає що буде виведене в консоль - бігом дивитися відео, там 2 хвилини.
console.log(0);
setTimeout(() => console.log(1));
new Promise((resolve) => {
  console.log(2);
  resolve(3);
}).then(console.log);
Якщо сподобалося - поставте лайк та пошерте. Я буду вдячним і відео буде більше. Якщо не сподобалося - напишіть що саме.

Зірки твіча з мене не буде хоча було весело. Тож продовжимо лупати скалу фронт-енду)

Анонси на сьогодні 19:00, Сергій Бабіч, Перша співбесіда нового сезону на Junior React JS. (деталі) 20:00, React їде в гості до CS-GO, просто граємо в прямому ефірі (твіч). П.М. В понеділок ввечері буде маленький сюрприз)

Анонси на сьогодні 19:00, Сергій Бабіч, Перша співбесіда нового сезону на Junior React JS. (деталі) 20:00, React їде в гості до CS-GO, просто граємо в прямому ефірі (твіч).

А що я вам приніс? 🤝 Дякую пані Єлізаветі за справжній приклад зі співбесіди https://youtu.be/LBz1aQtYot8

Беріть чай/каву/кота/собаку/тарантула та заходьте

Сьогодні, 19:00, Народний проект, частина 2. Будемо продовжувати. Розраховуємо до двох годин, десь так. В програмі деплоймент і useExternal хук Лінка вже на сам ефір

Підсумки по збору на грілки Зібрано: Банка: 9000 грн ПБ: 300 грн Попередній залишок: 16грн Сума: 9316 Придбано: Грілки для ні
+2
Підсумки по збору на грілки Зібрано: Банка: 9000 грн ПБ: 300 грн Попередній залишок: 16грн Сума: 9316 Придбано: Грілки для ніг HeatPaxx, 8 годин, 160 шт. по 30 грн Грілки для рук ThermoPaxx, 10 годин, 116 штук по 30 гривень. Доставка 265 гривень, адресна. Сума: 8545 гривень. Залишок: 9316 - 8545 = 771 (тепер є банка де ви можете бачите всі залишки) Takehot на той момент закінчилися, а їх грілка для ніг в моєму кармані пропрацювала 2 години. Розглядався варіант з Декатлоном, але ті що ми взяли були перевірені, а Декатлон ні. Якщо не буде заперечень, залишок відправлю на збір на машину одному підрозділу, про них буде трохи пізніше. Дякую всім хто долучився, ми зробили маленьку, але дуже корисну справу, ви це самі розумієте. На наступний збір знайду вам щось гарне на розіграш. Може книжку? Чи мерч? Бережіть себе і допомагайте ЗСУ та один одному.

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

Інструкція, як встановити канаркову версію React npm init vite react-canary cd react-canary npm i npm i react@18.3.0-canary-2
Інструкція, як встановити канаркову версію 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

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

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

Ось приклад найпростішого! компоненту, якому потрібно отримати асинхронні дані
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 його назвали, не знаю)

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