Skip to content

Latest commit

 

History

History
208 lines (152 loc) · 8.41 KB

middleware.ru.mdx

File metadata and controls

208 lines (152 loc) · 8.41 KB

import { Callout } from 'nextra-theme-docs'

Промежуточное программное обеспечение (ППО) (Middleware)

Обновитесь до последней версии (≥ 1.0.0), чтобы использовать этот функционал.

Функционал ППО — это новое дополнение в SWR 1.0, которое позволяет вам выполнять логику до и после SWR хуков.

Использование [#usage]

Промежуточное ПО получает SWR хук и может выполнять логику до и после его запуска. Если ППО несколько, каждый ППО оборачивает последующий. Последний ППО в списке получит исходный хук SWR — useSWR.

API [#api]

Примечание: Имя функции не должно быть написано с заглавной буквы (например, myMiddleware вместо MyMiddleware), иначе правила линтера React будут выдавать ошибку Rules of Hook

TypeScript

function myMiddleware (useSWRNext) {
  return (key, fetcher, config) => {
    // До выполнения хука...

    // Обработка следующего ППО, или хука `useSWR`, если это последнее.
    const swr = useSWRNext(key, fetcher, config)

    // После выполнения хука...
    return swr
  }
}

Вы можете передать массив из нескольких ППО как опцию SWRConfig или useSWR:

<SWRConfig value={{ use: [myMiddleware] }}>

// или...

useSWR(key, fetcher, { use: [myMiddleware] })

Расширение [#extend]

Промежуточное ПО расширяется как обычные опции. Например:

function Bar () {
  useSWR(key, fetcher, { use: [c] })
  // ...
}

function Foo() {
  return (
    <SWRConfig value={{ use: [a] }}>
      <SWRConfig value={{ use: [b] }}>
        <Bar/>
      </SWRConfig>
    </SWRConfig>
  )
}

эквивалентно:

useSWR(key, fetcher, { use: [a, b, c] })

Множество промежуточных ПО [#multiple-middleware]

Каждое ППО обворачивает последующее, а последнее ППО обворачивает SWR хук. Например:

useSWR(key, fetcher, { use: [a, b, c] })

Порядок выполнения ППО будет a → b → c, как показано ниже:

вход в  a
  вход в  b
    вход в  c
      useSWR()
    выход из  c
  выход из  b
выход из  a

Примеры [#examples]

Регистратор запросов [#request-logger]

Давайте в качестве примера создадим простой ППО — регистратора запросов. Он выводит все запросы fetcher-а, отправленные с этого хука SWR. Вы также можете использовать этот ППО для всех хуков SWR, добавив его в SWRConfig.

function logger(useSWRNext) {
  return (key, fetcher, config) => {
    // Добавим регистратор в исходный fetcher.
    const extendedFetcher = (...args) => {
      console.log('SWR запрос:', key)
      return fetcher(...args)
    }

    // Выполняем хук с новым fetcher-ом.
    return useSWRNext(key, extendedFetcher, config)
  }
}

// ... внутри вашего компонента
useSWR(key, fetcher, { use: [logger] })

Каждый раз, когда запрос запускается, он выводит ключ SWR в консоль:

SWR запрос: /api/user1
SWR запрос: /api/user2

Сохранение предыдущего результата [#keep-previous-result]

Иногда вы хотите, чтобы данные, возвращаемые useSWR, были «запаздывающими». Даже если ключ изменится, вы все равно хотите, чтобы он возвращал предыдущий результат, пока не загрузятся новые данные.

Это может быть построено как замедленное ППО используя useRef. В этом примере мы также собираемся расширить возвращаемый объект хука useSWR:

import { useRef, useEffect, useCallback } from 'react'

// Это ППО SWR для хранения данных даже при изменении ключа.
function laggy(useSWRNext) {
  return (key, fetcher, config) => {
    // Используйте ссылку для хранения ранее возвращённых данных.
    const laggyDataRef = useRef()

    // Фактический хук SWR.
    const swr = useSWRNext(key, fetcher, config)

    useEffect(() => {
      // Обновите ссылку если данные определены.
      if (swr.data !== undefined) {
        laggyDataRef.current = swr.data
      }
    }, [swr.data])

    // Предоставьте метод очистки запаздывающих данных, если таковые имеются.
    const resetLaggy = useCallback(() => {
      laggyDataRef.current = undefined
    }, [])

    // Возврат к предыдущим данным, если текущие данные не определены.
    const dataOrLaggyData = swr.data === undefined ? laggyDataRef.current : swr.data

    // Показывает предыдущие данные?
    const isLagging = swr.data === undefined && laggyDataRef.current !== undefined

    // Также добавьте поле `isLagging` в SWR.
    return Object.assign({}, swr, {
      data: dataOrLaggyData,
      isLagging,
      resetLaggy,
    })
  }
}

Когда вам нужно, чтобы хук SWR работал с задержкой, вы можете использовать это ППО:

const { data, isLagging, resetLaggy } = useSWR(key, fetcher, { use: [laggy] })

Сериализация ключей объекта [#serialize-object-keys]

Начиная с версии SWR 1.1.0 объектно-подобные ключи будут автоматически сериализоваться «из коробки». В более старых версиях (< 1.1.0) SWR **поверхностно** сравнивает аргументы при каждом рендеринге и запускает повторную проверку, если какой-либо из них изменился. Если вы передаете сериализуемые объекты в качестве ключа. Вы можете сериализовать ключи объекта, чтобы обеспечить его стабильность, может помочь простое промежуточное ПО:
function serialize(useSWRNext) {
  return (key, fetcher, config) => {
    // Сериализуйте ключ.
    const serializedKey = Array.isArray(key) ? JSON.stringify(key) : key

    // Передайте сериализованный ключ и десериализуйте его в fetcher-е.
    return useSWRNext(serializedKey, (k) => fetcher(...JSON.parse(k)), config)
  }
}

// ...
useSWR(['/api/user', { id: '73' }], fetcher, { use: [serialize] })

// ... или включите его глобально с помощью
<SWRConfig value={{ use: [serialize] }}>

Вам не нужно беспокоиться о том, что объект может измениться между рендерами. Он всегда сериализуется в одну и ту же строку, и fetcher по-прежнему получит эти аргументы объекта.

Кроме того, вы можете использовать такие библиотеки, как [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) вместо `JSON.stringify` — быстрее и стабильнее.