ローダーの再エクスポート
routeAction$
と routeLoader$
は、通常、routesDir ディレクトリ内の layout.tsx、index.tsx、plugin.tsx などのルート境界ファイルで宣言されます。ドキュメントはこちら。
ルート境界外で宣言したい場合があります。これは、再利用可能なロジックまたはライブラリを作成する場合に役立ちます。そのような場合、この関数をルーター境界内から再エクスポートすることが不可欠です。そうでない場合、実行されなかったり、例外がスローされたりします。
解決策
カスタムパスで 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'];
});
これで、./src/routes/index.tsx
のようなパスで共通の routeAction$
と routeLoader$
を使用できます。
import { component$ } from '@builder.io/qwik';
import { Form } from '@builder.io/qwik-city';
import { useCommonRouteAction, useCommonRouteLoader } from './shared/loaders';
// As mentioned, here we are re-exporting them
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">response:</div>
<div class="text-lg font-bold mb-4">
{commonRouteAction.value?.data.join(' ') || ''}
</div>
<button type="submit">Submit</button>
</Form>
<div>
<div class="mb-2">CommonRouteLoader</div>
<div class="mb-4">response:</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';
// As mentioned, here we are re-exporting the third-party loader
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">Card Number</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">Valid</p>
<p class="tracking-wider">11/15</p>
</div>
<div>
<p class="font-medium">Expiry</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>
);
});