prefer-modal-launcher
presentModal呼び出しをlaunch*launcher関数内に置くことを要求する。
- ⭐️ このルールは
plugin:@rdlabo/rules/recommendedプリセットに含まれます。
呼び出し側は helper.presentModal(...) をインラインで書かず、await launchXxxPage(helper, props) を使う必要があります。
各modalページは次をエクスポートするべきです。
XxxProps/XxxDismiss型presentModalを包むlaunchXxxPage(helper, props)
@rdlabo/rules/deny-overlay-create および @rdlabo/rules/deny-element と併用します。
ルール詳細
❌ 誤り: 呼び出し側で presentModal をインライン実行する
export class ExamplePage {
readonly helper = inject(HelperService);
async open() {
await this.helper.presentModal(OtherPage, {}); // error
}
}
次も誤りです。
export async function openModal(overlay: Helper) {
await overlay.presentModal(ExamplePage, {}); // error — name does not match /^launch/
}
const show = () => overlay.presentModal(ExamplePage, {}); // error
✅ 正しい: presentModal はlauncher内だけに置く
export interface OtherProps {
id: number;
}
export type OtherDismiss = { saved: boolean } | undefined;
export const launchOtherPage = (
helper: HelperService,
props: OtherProps,
): Promise<OtherDismiss> => {
return helper.presentModal(OtherPage, props, { watchKeyboard: false });
};
export class ExamplePage {
readonly helper = inject(HelperService);
async open() {
const data = await launchOtherPage(this.helper, { id: 1 });
if (data?.saved) {
// ...
}
}
}
launcher内のネストした呼び出しは問題ありません。
export const launchExamplePage = (overlay: Helper, props: Props) => {
const run = () => overlay.presentModal(ExamplePage, props);
return run();
};
オプション
{
// Method names treated as overlay presenters.
// default: ['presentModal']
presentMethodNames?: string[];
// RegExp source for allowed enclosing function / method names.
// default: '^launch'
launcherNamePattern?: string;
}
'@rdlabo/rules/prefer-modal-launcher': [
'error',
{
presentMethodNames: ['presentModal'],
launcherNamePattern: '^launch',
},
],
プロジェクトが open* launcherを使う場合は次のようにします。
{
launcherNamePattern: '^(launch|open)';
}