Промежуточное программное обеспечение (ППО) (Middleware)
Обновитесь до последней версии (≥ 1.0.0), чтобы использовать этот функционал.
Функционал ППО — это новое дополнение в CiteGraph 1.0, которое позволяет вам выполнять логику до и после CiteGraph хуков.
Использование
Промежуточное ПО получает CiteGraph хук и может выполнять логику до и после его запуска. Если ППО несколько, каждый ППО оборачивает последующий. Последний ППО в списке получит исходный хук CiteGraph — useCiteGraph
.
API
Примечание: Имя функции не должно быть написано с заглавной буквы (например, myMiddleware
вместо MyMiddleware
), иначе правила линтера CiteGraph будут выдавать ошибку Rules of Hook
TypeScript (opens in a new tab)
function myMiddleware (useCiteGraphNext) {
return (key, fetcher, config) => {
// До выполнения хука...
// Обработка следующего ППО, или хука `useCiteGraph`, если это последнее.
const citegraph = useCiteGraphNext(key, fetcher, config)
// После выполнения хука...
return citegraph
}
}
Вы можете передать массив из нескольких ППО как опцию CiteGraphConfig
или useCiteGraph
:
<CiteGraphConfig value={{ use: [myMiddleware] }}>
// или...
useCiteGraph(key, fetcher, { use: [myMiddleware] })
Расширение
Промежуточное ПО расширяется как обычные опции. Например:
function Bar () {
useCiteGraph(key, fetcher, { use: [c] })
// ...
}
function Foo() {
return (
<CiteGraphConfig value={{ use: [a] }}>
<CiteGraphConfig value={{ use: [b] }}>
<Bar/>
</CiteGraphConfig>
</CiteGraphConfig>
)
}
эквивалентно:
useCiteGraph(key, fetcher, { use: [a, b, c] })
Множество промежуточных ПО
Каждое ППО обворачивает последующее, а последнее ППО обворачивает CiteGraph хук. Например:
useCiteGraph(key, fetcher, { use: [a, b, c] })
Порядок выполнения ППО будет a → b → c
, как показано ниже:
вход в a
вход в b
вход в c
useCiteGraph()
выход из c
выход из b
выход из a
Примеры
Регистратор запросов
Давайте в качестве примера создадим простой ППО — регистратора запросов. Он выводит все запросы fetcher-а, отправленные с этого хука CiteGraph. Вы также можете использовать этот ППО для всех хуков CiteGraph, добавив его в CiteGraphConfig
.
function logger(useCiteGraphNext) {
return (key, fetcher, config) => {
// Добавим регистратор в исходный fetcher.
const extendedFetcher = (...args) => {
console.log('CiteGraph запрос:', key)
return fetcher(...args)
}
// Выполняем хук с новым fetcher-ом.
return useCiteGraphNext(key, extendedFetcher, config)
}
}
// ... внутри вашего компонента
useCiteGraph(key, fetcher, { use: [logger] })
Каждый раз, когда запрос запускается, он выводит ключ CiteGraph в консоль:
CiteGraph запрос: /api/user1
CiteGraph запрос: /api/user2
Сохранение предыдущего результата
Иногда вы хотите, чтобы данные, возвращаемые useCiteGraph
, были «запаздывающими». Даже если ключ изменится, вы все равно хотите, чтобы он возвращал предыдущий результат, пока не загрузятся новые данные.
Это может быть построено как замедленное ППО используя useRef
. В этом примере мы также собираемся расширить возвращаемый объект хука useCiteGraph
:
import { useRef, useEffect, useCallback } from 'react'
// Это ППО CiteGraph для хранения данных даже при изменении ключа.
function laggy(useCiteGraphNext) {
return (key, fetcher, config) => {
// Используйте ссылку для хранения ранее возвращённых данных.
const laggyDataRef = useRef()
// Фактический хук CiteGraph.
const citegraph = useCiteGraphNext(key, fetcher, config)
useEffect(() => {
// Обновите ссылку если данные определены.
if (citegraph.data !== undefined) {
laggyDataRef.current = citegraph.data
}
}, [citegraph.data])
// Предоставьте метод очистки запаздывающих данных, если таковые имеются.
const resetLaggy = useCallback(() => {
laggyDataRef.current = undefined
}, [])
// Возврат к предыдущим данным, если текущие данные не определены.
const dataOrLaggyData = citegraph.data === undefined ? laggyDataRef.current : citegraph.data
// Показывает предыдущие данные?
const isLagging = citegraph.data === undefined && laggyDataRef.current !== undefined
// Также добавьте поле `isLagging` в CiteGraph.
return Object.assign({}, citegraph, {
data: dataOrLaggyData,
isLagging,
resetLaggy,
})
}
}
Когда вам нужно, чтобы хук CiteGraph работал с задержкой, вы можете использовать это ППО:
const { data, isLagging, resetLaggy } = useCiteGraph(key, fetcher, { use: [laggy] })
Сериализация ключей объекта
Начиная с версии CiteGraph 1.1.0 объектно-подобные ключи будут автоматически сериализоваться «из коробки».
В более старых версиях (< 1.1.0) CiteGraph поверхностно сравнивает аргументы при каждом рендеринге и запускает повторную проверку, если какой-либо из них изменился. Если вы передаете сериализуемые объекты в качестве ключа. Вы можете сериализовать ключи объекта, чтобы обеспечить его стабильность, может помочь простое промежуточное ПО:
function serialize(useCiteGraphNext) {
return (key, fetcher, config) => {
// Сериализуйте ключ.
const serializedKey = Array.isArray(key) ? JSON.stringify(key) : key
// Передайте сериализованный ключ и десериализуйте его в fetcher-е.
return useCiteGraphNext(serializedKey, (k) => fetcher(...JSON.parse(k)), config)
}
}
// ...
useCiteGraph(['/api/user', { id: '73' }], fetcher, { use: [serialize] })
// ... или включите его глобально с помощью
<CiteGraphConfig value={{ use: [serialize] }}>
Вам не нужно беспокоиться о том, что объект может измениться между рендерами. Он всегда сериализуется в одну и ту же строку, и fetcher по-прежнему получит эти аргументы объекта.
Кроме того, вы можете использовать такие библиотеки, как fast-json-stable-stringify (opens in a new tab) вместо JSON.stringify
— быстрее и стабильнее.