Обложка канала

Заметки про React. Страница 9

Короткие и полезные заметки про React

  • Заметки про React

    Получение данных и Suspense Suspense позволяет приостановить рендеринг компонента. Например, если в нем выполняются асинхронные операции, такие как получение данных, то Suspense отложит рендер данного компонента. Но как Suspense понимает, что внутри компонента происходит сетевой запрос на получение данных? Suspense рендерит индикатор загрузки, но в коде мы нигде не сообщаем React, что делаем сетевой запрос. Если вы используете библиотеки react-query, SWR, то в них есть поддержка Suspense. Давайте попробуем сделать поддержку Suspense для Axios. Чтобы Suspense узнал о том, что в компоненте происходит асинхронная операция, нужно выкинуть исключение в виде промиса. Можно сделать функцию, которая бы делала это с любыми промисами и обернуть ее в сетевые запросы:
    const dataFetch = () => {
      const userPromise = fetchUser;
      return {
        user: wrapPromise(userPromise),
      };
    };
    const wrapPromise = (promise) => {
      let status = "pending";
      let result;
      let suspend = promise().then(
        (res) => {
          status = "success";
          result = res;
        },
        (err) => {
          status = "error";
          result = err;
        }
      );
      return {
        read() {
          if (status === "pending") {
            throw suspend;
          } else if (status === "error") {
            throw result;
          } else if (status === "success") {
            return result;
          }
        },
      };
    };
    
    Применение данной функции:
    const resource = dataFetch();
    const UserProfile = () => {
      const user = resource.user.read();
      return (
        <div className="container">
          <h1 className="title">{user.name}</h1>
        </div>
      );
    };
    
    Таким образом, Suspense увидит, что в компоненте UserProfile происходит сетевой запрос и покажет индикатор загрузки. blog.openreplay.com/data-fe…in-react
    Data fetching with Suspense in React

    Use the new Suspense technique for simpler data fetching

    OpenReplay Blog
  • Заметки про React

    React Query FAQ Доминик Дорфмайстер, один из разработчиков библиотеки React Query, написал в своем блоге FAQ по библиотеке react-query, в которой ответил на наиболее популярные вопросы. - Как передать параметр в refetch? Если кратко, то это сделать нельзя, т.к. нарушается принцип работы react-query. React-query кэширует результат запроса по ключу, переданному в хук в первом параметре, поэтому refetch только повторяет запрос. Если нужно выполнить refetch с другими параметрами, то это значит, что нужно сделать новый запрос с новым ключом.
    const { data } = useQuery(['item', id], () => fetchItem({ id }))
    
    - Состояние загрузки. Чтобы сохранить предыдущее значение data при изменении ключа до загрузки новых данных, можно использовать параметр keepPreviousData. Дополнительно можно использовать флаг isPreviousData, который обозначает что в data находится устаревшее значение.
    const { data, isPreviousData } = useQuery(
      ['item', id],
      () => fetchItem({ id }),
      { keepPreviousData: true }
    )
    
    - Почему не обновляется кэш? При работе напрямую с Query Cache бывают моменты, когда кэш не обновляется. Одна из причин – не совпадают ключи. Когда вызываете queryClient.setQueryData, ключи запроса должны полностью совпадать с существующими. Например, следующие ключи не будут совпадать, потому что ‘1’ !== 1:
    ['item', '1']
    ['item', 1]
    
    Еще одна возможная причина того, что не обновляет кэш – нестабильная ссылка на QueryClient в QueryClientProvider. Лучше всего объявлять QueryClient вне компонента, но если нужно объявить его внутри компонента, то объявляйте внутри рефа или useState:
    export default function App() {
      const [queryClient] = React.useState(() => new QueryClient())
    
      return (
        <QueryClientProvider client={queryClient}>
          <Example />
        </QueryClientProvider>
      )
    }
    
    https://tkdodo.eu/blog/react-query-fa-qs
    React Query FAQs

    Answering the top 3 most frequently asked React Query questions

    tkdodo.eu
  • Заметки про React

    Возможно вам не нужны эффекты Эффекты – это выход из парадигмы React. Они позволяют синхронизировать компоненты с какой-либо внешней системой, такой как виджет, не относящийся к React, сеть или DOM браузера. Если не задействована какая-то внешняя система (например, изменение стейта при обновлении какого-то пропа), вам не нужен эффект. Основные случаи, когда эффект не нужен: - Обновление стейта при обновлении стейта или пропа. Вместо этого используйте производные переменные. - Кэширование вычислений. Используйте useMemo. - Сброс стейта при изменении пропа. Установите изменяющийся проп в проп key. При изменении key, React пересоздает DOM и сбрасывает стейт у компонента и всех его потомков. - Получение данных. Если делаете fetch в эффекте, то используйте cleanup функцию для отмены запроса, чтобы предотвратить race condition. Также есть комментарий Дэна Абрамова про рекомендованный способ получения данных в React 18. beta.reactjs.org/learn/y…n-effect
    What is the recommended way to load data for React 18?

    In the past, when I've had a page that I need to fetch data for, I would put the request in a useEffect hook that would run once when the...

    reddit
  • Реклама

  • Заметки про React

    Storybook Community Showcase Сводка последних новостей от сообщества Storybook: энциклопедия компонентов, плагин Figma, Story Explorer и различные аддоны: Variants, переменные CSS, Recoil… - Энциклопедия компонентов. В Storybook собрали большую коллекцию популярных UI библиотек от Airbnb, Wix, WordPress и других. Теперь при создании своей UI библиотеки можно подсмотреть идеи у лучших компаний. - Figma плагин для дизайн ревью. С помощью плагина Storybook Connect можно смотреть Storybook истории прямо в дизайне фигмы и тестировать компонент в живую. - Обозреватель историй VSCode. Позволяет запускать истории в редакторе. storybook.js.org/blog/co…owcase-2
    Component Encyclopedia | Storybook

    Explore 1000s of components and libraries

    storybook.js.org
  • Заметки про React

    Обзор Redux Toolkit Если вы еще не пробовали Redux Toolkit (RTK), то рекомендую прочитать краткий обзор от Марка Эриксона, создателя данного инструмента. В нем он рассказывает об основных API и подходах к разработке с использованием RTK, а также призывает всех пользователей Redux начать использовать RTK. Если кратко, то основные тезисы в пользу использования RTK: - упрощает настройку стора до вызова одной функции; - устраняет случайную мутацию стора и упрощает изменение стейта; - избавляет от необходимости ручного написания action creators; - упрощает написание логики фичи в одном файле вместо распределения его по нескольким файлам; - хорошая поддержка TypeScript из коробки; - RTK Query позволяет избавиться от написания thunks, редьюсеров, actions creators и дополнительных хуков для управления данными и отслеживанием стейта запроса; https://blog.isquaredsoftware.com/presentations/2022-06-modern-redux-rtk/?slideIndex=0&stepIndex=0
    Modern Redux with Redux Toolkit, June 2022

    Presentation slides for this talk, June 2022

    Isquaredsoftware
  • Заметки про React

    Компонент и элемент в React В терминах React встречаются такие слова как компонент, элемент и экземпляр. Чтобы разобраться в них и понять как они работают, давайте посмотрим на примеры:
    const App = () => {
      return <p>Hello React</p>;
    };
    
    Код выше является объявлением React компонента. Если конкретнее, то это функциональный компонент (объявления классовых компонентов тоже являются компонентами). Рендеринг компонента происходит, когда мы используем его этот компонент как React элемент с угловыми скобками (например <Greeting />) в другом компоненте:
    const Greeting = ({ text }) => {
      return <p>{text}</p>;
    };
    
    const App = () => {
      return <Greeting text="Hello React" />;
    };
    
    Мы можем отрендерить компонент как элемент несколько раз. Каждый раз, когда мы рендерим компонент как элемент, мы создаем экземпляр данного компонента:
    const App = () => {
      return (
        <>
          <Greeting text="Hello Instance 1 of Greeting" />
          <Greeting text="Hello Instance 2 of Greeting" />
        </>
      );
    };
    
    Хоть компонент и объявлен один раз, он может использоваться несколько раз. При рендере он становится экземпляром компонента и живет в дереве React. Робин Верух в своем блоге разобрался, как происходит рендер элементов и почему не стоит вызывать компонент как функцию при рендере в другом компоненте. www.robinwieruch.de/react-e…omponent
    React Element vs Component

    What are React Elements, Components, and Instances? A step by step explanation for a better ...

    www.robinwieruch.de
  • Заметки про React

    TypeScript шпаргалка для React Если вы уже работаете с React и JS и планируете использовать TypeScript, то рекомендую изучить данный сайт. В нем собраны и разбиты по категориям инструкции по работе с React и TypeScript: как использовать TS вместе с хуками, функциональными компонентами, классами и т.д. Также есть раздел со списком полезных паттернов для React появившемся в определенной версии TypeScript. Например, в ​​TypeScript 4.1 появились типы шаблонных литералов, которые позволяют моделировать динамические типы в строковых литералах. Это может использоваться при типизации роутера:
    type ParseRouteParams<Rte> = Rte extends `${string}/:${infer P}` ? P : never;
    type Params = ParseRouteParams<"/api/user/:userID">; // Params is "userID"
    
    https://react-typescript-cheatsheet.netlify.app/
    React TypeScript Cheatsheets | React TypeScript Cheatsheets

    react-typescript-cheatsheet.netlify.app
  • Заметки про React

    Инверсия управления и внедрение JSX через Context API Инверсия управления – это принцип проектирования, который позволяет вызывающему коду контролировать внешнее окружение вызываемой программы. Использование этого принципа в React позволяет создавать более гибкие и кастомизируемые компоненты. Для того, чтобы показать как использовать этот принцип в React, автор создал компонент переиспользуемой таблицы, в которой есть отдельный столбец с действиями над строками. У каждой строки может быть свой набор действий и, чтобы контролировать это, можно использовать IoC. Для того чтобы рендерить для каждой строки кастомный набор действий, можно использовать контекст для передачи функции рендера. Функция рендера будет возвращать готовый JSX для рендера, который будет контролировать компонент, использующий таблицу.
    const TableColumnActions = props => {
      const { row, column } = props;
      const [openActions, setOpenActions] = useState(false);
      useOnClickOutside(popupRef, () => setOpenActions(false));
      const renderMenu = useTableActionsContext();
    
      const menuOptions = renderMenu({
        row,
        column,
        styles,
      });
    
      return (
        <div className="relative">
          {openActions ? (
              <ul className={styles.actionsMenu}>{menuOptions}</ul>
          ) : null}
        </div>
      );
    };
    
    theroadtoenterprise.com/blog/re…text-api
    React Enterprise Component Patterns - Inversion of Control and JSX Injection via Context API

    In this article we will cover how to provide content to a deeply nested component by injecting JSX into a deeply nested component via Context API.

    The Road To Enterprise Blog
  • Заметки про React

    React Labs: над чем мы работали – июнь 2022 React Labs — это новая серия статей: команда React хочет чаще делиться своим прогрессом. Команда работает над несколькими проектами и делится информацией о текущем состоянии. Это не дорожная карта, а исследовательские проекты, которые могут попасть в релиз. - Серверные компоненты. Вместо использования внешней библиотеки для I/O будет использоваться async/await для лучшей совместимости. Откажутся от расширения у серверных файлов .server.js в пользу аннотаций внутри файла. Работают над унификацией для поддержки сборщиков Webpack/Vite. - Asset Loading. Интеграция загрузки изображений, шрифтов, стилей и Suspense. Загрузка ассетов должна блокировать отображение, но не конкурентный рендеринг и стриминг. - React Optimizing Compiler. Представили компилятор React Forget на React Conf 2021. Работа идет, недавно переписали компилятор на новую архитектуру. - Offscreen. Предлагает новые возможности, например, мгновенный переход – рендер компонента в фоне. reactjs.org/blog/20…022.html
    React Labs: What We've Been Working On – June 2022 – React Blog

    React 18 was years in the making, and with it brought valuable lessons for the React team. Its release was the result of many years of research and exploring many paths. Some of those paths were successful; many more were dead-ends that led to new insights. One lesson we’ve learned is that it’s frustrating for the community to wait for new features without having insight into these paths that we’re exploring. We typically have a number of projects being worked on at any time, ranging from the…

    reactjs.org
  • Заметки про React

    Jest Preview для дебага тестов При написании тестов с использованием Testing Library приходится писать много запросов в DOM, держа в голове структуру страницы, которую рендерит React для теста. Для того чтобы видеть результат рендера во время теста, можно использовать библиотеку Jest Preview. После установки библиотеки и настройки конфигов, необходимо во время запуска тестов запускать команду jest-preview, которая будет стартовать сервер для превью тестов. В самих тестах, для отображения в браузере текущего DOM компонента, используется функция preview.debug(). Стоит учитывать, что в текущий момент библиотека активно развивается и может работать нестабильно. https://www.jest-preview.com/
  • Заметки про React

    Plasmo – React фрейморвк для создания браузерных расширений Plasmo – новый фреймворк на React и TypeScript для создания браузерных расширений. Особенности: - live-reloading при дев разработке; - файлы окружений; - автоматический деплой; - автоматическая генерация manifest.json; - поддержка всех основных браузеров; Также есть CLI для инициализации проекта. В фреймворке есть дополнительные библиотеки для работы с расширениями, например API постоянного хранилища, у которой есть интеграция с Redux. https://docs.plasmo.com/
    Documentation | Plasmo

    Plasmo Framework is a battery-packed browser extension SDK made by hackers for hackers. Build your product and stop worrying about config files and the odd peculiarities of building browser extensions. Get started using Plasmo with the official documentation, and explore all of our features!

    Plasmo Docs
  • Заметки про React

    Пример использования startTransition и 3D-рендеринга В React 18 был добавлен конкурентный рендеринг. Основная его идея в том, что обновления стейта можно разделить на две категории: - Срочные обновления: обеспечивают оперативный отклик на пользовательские события, например, ввод текста или скролл. - Переходные обновления: представляют несрочные задачи для рендера UI, например, отображение датасета. Цель переходных обновлений состоит в том, чтобы создать более отзывчивый интерфейс. До React 18 все обновления стейта считались срочными и ввод текста или клик могли зафризить UI при рендере тяжелого компонента. В React 18 с помощью переходных обновлений рендер тяжелых компонентов будет происходить в фоне, в то время как UI будет оставаться отзывчивым. Конкурентный рендеринг может выполнять следующие вещи: - Yielding: React периодически ставит работу рендера на паузу, чтобы дать браузеру сделать другую работу. - Прерывание: при появлении срочных задач React ставит рендер несрочной задачи на паузу и начинает рендерить срочную задачу, чтобы UI оставался отзывчивым. - Отбрасывание старых результатов: если данные стейта для перехода устарели, то React отбрасывает старый рендер и начинает рендер по новой для свежего стейта. Доу-Чи Лиу в своем блоге показал, как использовать API конкурентного рендеринга startTransition для рендера тяжелого компонента с 3D моделью с визуализацией связей между пользователями в Github. Приложение содержит два компонента: - поисковая строка пользователя Github; - сцена с 3D визуализацией связей на three.js и react-three-fiber; dawchihliou.github.io/article…react-18
    Stress Testing Concurrent Features in React 18: A Case Study of startTransition & 3D Rendering

    React 18 released the highly anticipated concurrent features. In this article, we are diving into a 3D visualization and discuss how to optimize its performance step by step with React 18's concurrent rendering.

    dawchihliou.github.io
  • Заметки про React

    Приглашаем всех JavaScript-разработчиков 23 июня в Питер на офлайн-день конференции HolyJS 2022 Spring! Вас ждут: ✔ 5 докладов. ✔ Дискуссии после каждого доклада. ✔ Lightning talks: мини-доклады от участников конференции. ✔ Живое общение, нетворкинг и обмен знаниями. ✔ Стенды партнеров с разными активностями, мини-докладами и мерчем. Кроме того, вместе с билетом на офлайн-день вы получите доступ к записям докладов и других активностей онлайн-части. Подробности, полную программу и билеты вы найдете по ссылке. Если покупаете билет за свой счет (а не за счет компании), то воспользуйтесь промокодом для получения скидки: reactnotes2022JRGpc
  • Заметки про React

    Как использовать useMemo и useCallback Скорее всего вы знакомы с хуками useMemo и useCallback. Эти хуки используются практически в каждом проекте, и чем больше они используются, тем больше усложняют код компонента. Многие используют эти хуки, не до конца понимая зачем они нужны, и пишут их, потому что все так делают, так проще. На самом деле большинство использований данных хуков неправильно и можно обойтись без них. В некоторых случаях приложение без них будет работать немного быстрее. Это не значит, что хуки useMemo и useCallback бесполезны, просто использовать их нужно в определенных случаях, а не всегда. Основная задача хуков useMemo и useCallback- это мемоизация между ре-рендерами компонента. Если какое-то непримитивное значение или функция объявлены в теле компонента, то каждый раз при рендере будет создаваться новая ссылка на значение. При мемоизации значение будет закэшировано во время первого рендера и при последующих рендерах будет возвращаться ссылка на закэшированное значение. Это удобно при использовании с useEffect:
    const Component = () => {
      // сохранение ссылк между ре-рендерами
      const a = useMemo(() => ({ test: 1 }), []);
    
      useEffect(() => {
        // будет вызван когда значение “a” изменится
      }, [a]);
    };
    
    Использование хуков useMemo и useCallback полезно только при ре-рендерах. При первом рендере React кэширует значения, поэтому рендерится компонент немного медленнее. Один из популярных вариантов использования хуков мемоизации – это предотвращение ререндера компонента путем мемоизации пропсов. Например:
    ​​const Item = ({ item, onClick }) => <button onClick={onClick}>{item.name}</button>;
    
    const Component = ({ data }) => {
      const value = useMemo(() => ({ a: someStateValue }), [someStateValue]);
      const onClick = useCallback(() => {
        console.log(value);
      }, [value]);
    
      return (
        <>
          {data.map((d) => (
            <Item item={d} onClick={onClick} />
          ))}
        </>
      );
    };
    
    В примере выше использование хуков нецелесообразно. Компонент ререндерится, если родительский компонент ререндерится. Чтобы предотвратить ререндер компонента, нужно использовать функцию React.memo. Компонент обернутый в React.memo будет ререндерится, только если изменятся пропсы. Поэтому все пропсы для этого компоненты должны быть мемоизированны. Однако, прежде чем мемоизировать все пропсы для компонента стоит проверить производительность компонента. Если компонент работает быстро, то мемоизация не нужна. www.developerway.com/posts/h…callback
    How to useMemo and useCallback: you can remove most of them

    What is the purpose of useMemo and useCallback hooks, mistakes and best practices in using them, and why removing most of them might be a good idea.

    Developer way
  • Заметки про React

    TypeScript типы для React Использование TypeScript при написании компонентов в React может существенно облегчить разработку и поддержку кода. Небольшая подборка утилитарных типов для работы с React: - React.ComponentProps. Иногда нет доступа к типу пропсов компонента: например, внешняя библиотека, которая дает доступ только к самому компоненту. Чтобы узнать тип пропсов компонента можно использовать React.ComponentProps.
    import { ComponentProps } from "react";
    import { ExternalComponent } from "external-lib";
    
    type InternalComponentProps = ComponentProps<typeof ExternalComponent> & {
      outerClassName: string;
    };
    
    - React.MouseEventHandler. Используется для типизации колбека события мыши.
    import { MouseEventHandler, } from "react";
    
    type ComponentProps = {
      caption: string;
      onClick: MouseEventHandler<HTMLButtonElement>;
    };
    
    const Component = (props: ComponentProps) => (
      <div>
        <button onClick={props.onClick}>{props.caption}</button>
      </div>
    );
    
    - Pick. Используется для создания нового типа объекта, принимает два аргумента: исходный тип объекта и список ключей для выбора из исходного объекта. В React можно использовать для создания интерфейса пропсов, когда какой-то интерфейс расшарен между несколькими.
    type ComponentProps = Pick<Something, "propA" | "propB" | "children"> & {
     wrapperClassName?: string;
    }
    
    export const Component = (props: ComponentProps) => (
    …
    ); 
    
    www.chakshunyu.com/blog/7-…velopers
    7 TypeScript Utility Types For React Developers

    It's hard to imagine React development without TypeScript nowadays. However, being a good React developer doesn’t automatically translate into being a good TypeScript developer. This article goes over 7 different utility types that are helpful to React developers on a daily basis.

    Chakshunyu
  • Реклама

  • Заметки про React

    Listener API в Redux Toolkit В RTK с самого начала используется redux-thunk в качестве дефолтного мидлвара для написания синхронной и асинхронной логики вне компонента. Однако, thunk не позволяет вызывать side effect функцию в ответ на dispatch экшена. Для таких целей обычно используется redux-saga. В redux-toolkit v1.8.0 появилось новое listener API, которое позволяет создавать мидлвар для подписки на экшен или изменении стейта. Концептуально новое API похоже на useEffect, которое запускается в ответ на изменении стора. Подписка может быть создана как в процессе создания стора через listenerMiddleware.startListening(), либо динамически в рантайме через dispatch(addListener()).
    // Create the middleware instance and methods
    const listenerMiddleware = createListenerMiddleware()
    
    // Add one or more listener entries that look for specific actions.
    // They may contain any sync or async logic, similar to thunks.
    listenerMiddleware.startListening({
      actionCreator: todoAdded,
      effect: async (action, listenerApi) => {
        // Run whatever additional side-effect-y logic you want here
        console.log('Todo added: ', action.payload.text)
    
        // Can cancel other running instances
        listenerApi.cancelActiveListeners()
    
        // Run async logic
        const data = await fetchData()
    
        // Pause until action dispatched or state changed
        if (await listenerApi.condition(matchSomeAction)) {
          // Use the listener API methods to dispatch, get state,
          // unsubscribe the listener, start child tasks, and more
          listenerApi.dispatch(todoAdded('Buy pet food'))
          listenerApi.unsubscribe()
        }
      },
    })
    
    Обзор и сравнение с redux-saga: blog.logrocket.com/redux-t…dux-saga
    Redux Toolkit's new listener middleware vs. Redux-Saga - LogRocket Blog

    Redux Toolkit's new listener middleware is a great alternative to Redux Saga, with a few caveats - learn all about it in this complete guide.

    LogRocket Blog
  • Заметки про React

    Бесплатный день HolyJS 2022 Spring! Команде организаторов и Программному комитету HolyJS хотелось бы, чтобы их усилия оценило как можно больше участников. Поэтому доступ к третьему дню конференции будет открыт для всех желающих. Community Day на HolyJS 2022 Spring — 10 июня доступ свободный В билет бесплатного дня входят: ✔ 4 доклада: например, про server-driven UI в вебе и преобразование TypeScript в Java. ✔ Воркшоп: спикеры покажут, как написать приложение для конвертации криптовалюты с микросервисной архитектурой с помощью gRPC на платформе Node.js. ✔ Дискуссии после докладов. ✔ Возможность поучаствовать в играх, квизах, конкурсах и других активностях от партнеров конференции — там можно не только круто провести время, но и получить ценные призы. ✔ Чаты, где сидят сотни ваших коллег со всего мира. Для участия в Community Day нужно только зарегистрироваться — для этого переходите по ссылке.
  • Заметки про React

    Как работает хук useInsertionEffect в React 18 CSS-in-JS библиотеки генерируют стили на лету и вставляют их в документ. Для этих библиотек важно знать, в какой момент можно вставлять теги <style> в документ, т.к. это может повлиять на производительность. При добавлении или удалении CSS правил браузер пересчитывает стили у всех элементов. Для того чтобы избежать лишнего пересчета стилей для элементов на странице при изменении CSS правил, необходимо изменять их одновременно с другим изменением DOM, например, когда React мутирует DOM, перед чтением макета (например clientWidth) и до отрисовки в браузере. Для того, чтобы добиться такого поведения, можно использовать хук useInsertionEffect. По сигнатуре он похож на useEffect, но он запускается синхронно перед изменениями DOM. Внутри хука можно изменять глобальные DOM элементы, такие как <style> или <defs>. Он запускается перед хуком useLayoutEffect. Основное предназначение данного хука – изменение стилей в CSS библиотеках.
    function useCSS(rule) {
      useInsertionEffect(() => {
        if (!isInserted.has(rule)) {
          isInserted.add(rule);
          document.head.appendChild(getStyleForRule(rule));
        }
      });
      return rule;
    }
    function App() {
      let className = useCSS(rule);
      return <div className={className} />;
    }
    
    blog.saeloun.com/2022/06…oneffect
    Know about the useInsertionEffect hook in React 18

    The useInsertionEffect hook in React 18 is mostly for CSS-in-JS libraries for inserting global DOM nodes like 'style' or SVG 'defs' in the document.

    Saeloun Blog