Реэкспорт загрузчиков
routeAction$
и routeLoader$
обычно объявляются в файлах маршрута, таких как layout.tsx, index.tsx и plugin.tsx в директории routes (документация).
Иногда вам может потребоваться объявить их вне границ маршрута. Это может быть полезно, когда вы хотите создать логику многократного использования или библиотеку. В таком случае необходимо, чтобы эта функция была реэкспортирована из границы маршрутизатора, иначе она не будет запущена или вызовет исключение.
Решение
Вы можете определить routeAction$
и routeLoader$
в своем пользовательском пути и реэкспортировать их в ваших файлах layout.tsx, index.tsx и plugin.tsx.
Пример многократно используемой логики
Представим, что у нас есть routeLoader$
, который проверяет, вошёл ли пользователь в систему или нет. Не имеет смысла копировать и вставлять один и тот же код в разные части нашего кода. Согласно хорошим практикам, идеальным способом является централизация логики. В этом примере мы объявляем routeAction$
и routeLoader$
в централизованном файле, чтобы затем повторно использовать их в других файлах.
Пример с ./shared/loaders.ts
import { routeAction$, routeLoader$ } from '@builder.io/qwik-city';
export const useCommonRouteAction = routeAction$(async () => {
// ...
return { success: true, data: ['Qwik', 'Partytown'] };
});
export const useCommonRouteLoader = routeLoader$(async () => {
// ...
return ['Mitosis', 'Builder.io'];
});
Теперь вы можете использовать ваши общие routeAction$
и routeLoader$
в путях, подобных этому ./src/routes/index.tsx
.
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useCommonRouteAction, useCommonRouteLoader } from './shared/loaders';
// Как уже говорилось, здесь мы реэкспортируем их
export { useCommonRouteAction, useCommonRouteLoader } from './shared/loaders';
export default component$(() => {
const commonRouteAction = useCommonRouteAction();
const commonRouteLoader = useCommonRouteLoader();
return (
<div class="flex justify-around text-xl">
<Form action={commonRouteAction}>
<div class="mb-2">CommonRouteAction</div>
<div class="mb-4">ответ:</div>
<div class="text-lg font-bold mb-4">
{commonRouteAction.value?.data.join(' ') || ''}
</div>
<button type="submit">Отправить</button>
</Form>
<div>
<div class="mb-2">CommonRouteLoader</div>
<div class="mb-4">ответ:</div>
<div class="text-lg font-bold mb-4">{commonRouteLoader.value.join(' ')}</div>
</div>
</div>
);
});
Пример с библиотекой сторонних разработчиков
Может случиться так, что нам понадобится интегрировать сторонние библиотеки, работу которых мы не контролируем. Давайте подумаем, например, об интеграции метода оплаты в наше приложение. Нам предоставляется компонент для интеграции в страницу, но мы не имеем никакого контроля над тем, что происходит под капотом этого компонента. Итак, если этой библиотеке нужны routeAction$
или routeLoader$
, мы должны реэкспортировать их, чтобы обеспечить корректную работу нашей библиотеки.
Вот наш код:
import { component$ } from '@builder.io/qwik';
import { ThirdPartyPaymentComponent } from './third-party-library';
// Как уже говорилось, здесь мы реэкспортируем сторонний загрузчик
export { useThirdPartyPaymentLoader } from './third-party-library';
export default component$(() => {
return (
<section>
<ThirdPartyPaymentComponent />
</section>
);
});
Здесь представлен код библиотеки:
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
export const useThirdPartyPaymentLoader = routeLoader$(() => {
return { name: 'John Doe' };
});
export const ThirdPartyPaymentComponent = component$(() => {
const thirdPartyPaymentLoader = useThirdPartyPaymentLoader();
return (
<div
class={[
'w-96 h-56 m-auto rounded-xl relative text-white font-bold shadow-2xl',
'transition-transform transform hover:scale-110 bg-gray-600',
]}
>
<div class="w-full px-8 absolute top-8">
<div class="flex justify-between">
<div class="">
<p>Name</p>
<p class="tracking-widest">{thirdPartyPaymentLoader.value.name}</p>
</div>
<img class="w-12 h-12" src="/logos/qwik-logo.svg" />
</div>
<div class="pt-1">
<p class="font-medium">Номер карты</p>
<p class="tracking-wider">4642 3489 9867 7632</p>
</div>
<div class="pt-6 pr-6">
<div class="flex justify-between text-xs">
<div>
<p class="font-medium">Действует с</p>
<p class="tracking-wider">11/15</p>
</div>
<div>
<p class="font-medium">Срок действия</p>
<p class="tracking-wider">03/25</p>
</div>
<div>
<p class="font-medium">CVV</p>
<p class="tracking-wider">···</p>
</div>
</div>
</div>
</div>
</div>
);
});