-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
エラーハンドラーからrouterを参照できない #1612
Comments
CataogView⇒ErrorHandler⇒router⇒catalogRoutes⇒CatalogViewという関係。 import { router } from '@/router';
|
対応案検討・調査したがうまくいかなかったもの storeでrouterをラップするrouteingStoreは使えるので、 router currentPath: router.currentRoute.value.fullPath,
navigateToNamedRoute(routeName: string) {
router.push({ name: routeName });
}, handler const routingStore = useRoutingStore();
routingStore.setRedirectFrom(routingStore.currentPath);
routingStore.navigateToNamedRoute('authentication/login');
showToast('ログインしてください。'); 循環参照
errorHandlerをVueのコンポーネント化する[Vue warn]: inject() can only be used inside setup() or functional components.
composableの例を下記で探してみたが、エラーハンドラーは見つからなかった。 plugin化あまりよくわかっていない状態。
|
ComposableとFunctional Componentsを混同していたが、これらは別物で、 |
plugin化この方法で回避できることを確認した。 App.vue// プラグイン呼び出す
app.use(customHandler); custom-handler.ts// routerをimportする
import { router } from '@/router';
// injectするクラスとメソッドを定義
class Handler {
static errorHandler()
}
// Plugin用のメソッド定義
export const customHandler = {
install: (app: App) => {
app.provide('customHandler', Handler);
},
}; View側// ハンドラーをinjectする
// このときcustomHandlerをimportしているわけではないので、循環参照にはならない
const customHandler: any = inject('customHandler');
// 一旦any
// 型情報だけのimportであれば循環参照にはならない…はず
const addBasket = async (catalogItemId: number) => {
try {
await addItemToBasket(catalogItemId);
router.push({ name: 'basket' });
} catch (error) {
customHandler.errorHandler(error, () => {
showToast('カートに追加できませんでした。');
});
}
}; |
describe('App.vue', () => {
it('トップページに遷移する', async () => {
const wrapper = mount(App, { global: { plugins: [router] } });
await router.isReady();
expect(wrapper.html()).toContain('Dressca 管理 トップ');
});
}); const wrapper = mount(ItemsAddView, {
global: { plugins: [pinia, router] },
}); |
Pluginの作り方vue-routerとpiniaを確認し、同じ構造だったため、これを一般的なものと考えて問題ないはず…。 createXX型解決のためにinterfaceを定義して、 export interface CustomErrorHandler {
// 略
export function createCustomErrorHandler(): CustomErrorHandler {
const customErrorHandler: CustomErrorHandler = {
install: (app: App) => {
app.provide(customErrorHandlerKey, customErrorHandler);
},
handle: (
// 略
return customErrorHandler;
} main.ts const customErrorHandler = createCustomErrorHandler();
app.use(customErrorHandler); useXXプラグインを利用したい子コンポーネントでは、直接injectを書かず、
定義 export function useCustomErrorHandler(): CustomErrorHandler {
return inject(customErrorHandlerKey)!;
} 子コンポーネントでの利用 const customErrorHandler = useCustomErrorHandler(); Injectionkeyプラグインは、アプリケーションレベルでprovide、子コンポーネントinjectして使用するが、
1箇所に定義し、利用するコンポーネントから呼び出せばよいので、べた書きのキー値が散らばることはない。 import type { InjectionKey } from 'vue';
import type { CustomErrorHandler } from './error-handler/custom-error-handler';
export const customErrorHandlerKey = Symbol(
'customErrorHandler',
) as InjectionKey<CustomErrorHandler>; |
テスト確認対象は下記。 カスタムエラーハンドラーコールバックは画面側で確認する。 共通処理
画面買い物かご
カタログ
チェックアウト
完了画面
|
ネットワークエラーの起こし方mockからレスポンスを返さないようにした状態で、 axiosはデフォルトではタイムアウトしない設定なので、ずっと待ち続ける。
|
コールバックと共通処理が被った場合の挙動既存の挙動として、 下記で注文が500エラーで失敗したときのアプリの挙動として、
少し違和感はあるが、いまのところ問題になるケースはなさそう…? CheckOutView.vue const checkout = async () => {
try {
// 略
} catch (error) {
customErrorHandler.handle(error, () => {
showToast('注文に失敗しました。');
router.push({ name: 'error' });
});
}
}; if (error instanceof CustomErrorBase) {
callback();
// エラーの種類によって共通処理を行う
// switch だと instanceof での判定ができないため if 文で判定
if (error instanceof UnauthorizedError) {
if (handlingUnauthorizedError) {
// 略
} else if (error instanceof ServerError) {
if (handlingServerError) {
handlingServerError();
} else {
showToast('サーバーエラーが発生しました。');
}
} |
ハンドラーがrouterに依存しているので、 app.use(customErrorHandler);
app.use(pinia);
app.use(router); |
下記の対応によりissueが解決したため、クローズします。 |
概要
フロントエンドのerrorHandler内でrouterを使おうと試みると、想定外の挙動をする。
詳細 / 機能詳細(オプション)
const router =use Router();
でrouterを使おうとすると下記の警告が出力される。[Vue warn]: inject() can only be used inside setup() or functional components.
useRouter()
が内部的にinject()を呼び出しているらしいが、errorHandlerはvueコンポーネントではないので、inject()を呼び出すことができない。
router.currentRoute
が取得できずにシステムエラーになってしまう。完了条件
ここにこの Issue の完了条件を箇条書きで記載します。
The text was updated successfully, but these errors were encountered: