OnVisibleの「書き方」は整理できた。では「何を書くか」は?
Part 1〜Part 3では、OnVisibleの構造を整理してきました。処理を画面自身に寄せ、Navigation Contextで入口を分岐し、Execution Planで中身の重複を排除する——OnVisibleの「書き方」は段階的に改善できました。
しかし、すべてをOnVisibleに集めてしまうと、不都合が生じる場合が出てきます。
この記事で伝えたいこと
- OnVisibleは「画面表示時に決まるデータ」を取得する場所であり、「何でも置く場所」ではない
- 「いつ決まるか」は、データのライフサイクルを考えることで、コードの配置場所を判断できる
- 静的な定義をコントロール自身に移すことで、OnVisibleの役割がより明確になる
前提
- Power Apps のCanvasアプリ
- 前回と同じ商品管理アプリの構成
- Part 1〜3で整理したOnVisibleの構造を導入済み
- AIと協働しながら、より良い設計パターンを試行錯誤中
OnVisibleが「便利な置き場所」になっていないか?
Part 1〜3の方針に従って、画面の初期化処理をOnVisibleに集約してきました。すると、こういうコードが自然と増えてきます。
MainScreen.OnVisible(肥大化した例)
// データソースからの取得
ClearCollect(colCategories, Categories);
ClearCollect(colProducts, Products);
// ソートの選択肢
UpdateContext({
locSortOptions: Table(
{Value: "Name", Display: "名前順"},
{Value: "Date", Display: "日付順"},
{Value: "Amount", Display: "金額順"}
)
});
// ステータスの選択肢
UpdateContext({
locStatusOptions: Table(
{Value: "active", Display: "生産中"},
{Value: "discontinued", Display: "生産終了"},
{Value: "pending", Display: "生産前"}
)
});
何が起きているか
一見、問題はなさそうです。初期化処理をOnVisibleにまとめるという方針に沿っています。
UIコントロールにどんな選択肢を持たせているのかも把握しやすいです。
しかし、よく見ると、locSortOptions や locStatusOptions は画面が表示されるたびに毎回同じ値を再設定しています。Navigateで画面を行き来するたびにOnVisibleが実行され、ソートの選択肢「名前順・日付順・金額順」という不変のリストを何度も作り直しています。
これ自体は性能上の大きな問題にはならないかもしれません。しかし、もっと本質的な問題があります。
OnVisibleに静的データと動的データが混在していると、「この画面が外部に何を依存しているか」がぼやける。
colCategories はデータソースから取得するものなので、画面表示のたびに最新を取りに行く意味があります。しかし locSortOptions はコードに直書きされた固定値です。この2つが同じ場所に並んでいると、OnVisibleを読んだときに「この画面はどのデータを外部から取得しているのか」を判断するのにノイズが生まれそうです。
また、単純にコード量が増えることで「注視しなければいけない対象」を増やしていることにもなります。
判断基準:「いつ決まるか」で配置を決める
OnVisibleに何を置くかを判断するために、データを**「いつ決まるか」**というライフサイクルで分類してみます。
| いつ決まるか | 配置場所 | 例 |
|---|---|---|
| 設計時に決まる(不変) | 各コントロールのプロパティに直接記述 | ソート順、表示形式の選択肢 |
| 画面表示時に決まる | OnVisible | DB取得、前画面から渡されたデータに依存する処理、外部データソースから取得する選択肢 |
| 操作中に変わる | OnChange等のイベント | 連動ドロップダウンの絞り込み |
この分類で先ほどのコードを見直すと、
-
colCategories,colProducts→ 画面表示時に決まる → OnVisibleに置く理由がある -
locSortOptions,locStatusOptions→ 設計時に決まる → OnVisibleに置く理由がない
静的な定義をコントロールに移す
Before:OnVisibleに全部置くパターン
// ❌ MainScreen.OnVisible
UpdateContext({
locSortOptions: Table(
{Value: "Name", Display: "名前順"},
{Value: "Date", Display: "日付順"},
{Value: "Amount", Display: "金額順"}
)
});
// DropDown_Sort.Items
locSortOptions
After:コントロールに直接書くパターン
// ✅ MainScreen.OnVisible → この定義はなし
// ✅ DropDown_Sort.Items
Table(
{Value: "Name", Display: "名前順"},
{Value: "Date", Display: "日付順"},
{Value: "Amount", Display: "金額順"}
)
何が変わるか
- OnVisibleが軽くなる:静的データの再生成がなくなり、画面遷移時の実行コストが下がる
- 画面の依存関係が明確になる:OnVisibleには「外部から取得するデータ」だけが残り、この画面が何に依存しているかが一目でわかる
-
コントロールの振る舞いが自己完結する:
UIコントロールを見れば選択肢がわかる。一度決めてほぼ変更がないなら見る頻度も低い。
この形に落ち着く背景にある2つの考え方
Colocation(コロケーション)
「データや定義は、それを使う場所のできるだけ近くに置け」という考え方です。Reactコミュニティで Kent C. Dodds が広めた概念で、コンポーネントが必要とするスタイル・ロジック・データを、そのコンポーネントの近くに配置することで、コードの見通しと保守性が向上するというものです。
静的な選択肢をOnVisibleではなくItemsに直接書くのは、まさにこのColocationの実践です。
Locality of Behavior(振る舞いの局所性)
htmxの Carson Gross が名付けた概念で、「コードの振る舞いは、そのコード自体の近くに可能な限りあるべきだ」という原則です。
DropDown_Sort.Items に選択肢が直接書いてあれば、そのドロップダウンの振る舞いはそこを見るだけで理解できます。OnVisibleに定義があると、「この選択肢はどこで作られているんだ?」とコードを追いかける必要が生まれます。
判断が迷うケース
「今は静的だけど、将来DBから取るかもしれない」
今静的なら、今はコントロールに置きます。将来的にデータソースから取得するようになったら、そのときにOnVisibleに移せばよいだけです。
起きるかわからない将来のためにOnVisibleに置いておくのは、YAGNI(You Aren't Gonna Need It)の原則に反します。
「複数のコントロールで同じ選択肢を使っている」
複数箇所に同じ定義を書くと、片方だけ修正してもう片方を直し忘れる。いわゆる二重管理の問題が出てきます。
重複が生まれた時点で、App.OnStart や App.Formulas で一度だけ定義して共通化する方向を検討するのが良さそうです。
「OnVisibleに全部書いてある方が一覧性がある」
一覧性自体はメリットです。しかし、OnVisibleは画面遷移のたびに実行される場所なので、改修や調査で頻繁に読み返すことになります。そこに「当分気にしなくていい静的な定義」と「今まさに気にしなければいけない動的な取得処理」が混在していると、読むたびに「これは今関係あるのか?」という判断コストが発生します。
気にしなくていいものを別の場所に移すだけで、OnVisibleを開いたときに目に入るのは「本当に注意を払うべき処理」だけになります。
まとめ
Part 1〜3ではOnVisibleの「書き方」を整理してきましたが、今回は一歩引いて、そもそも何をOnVisibleに置くべきかという「配置」の問題を考えました。
判断基準はシンプルです。「いつ決まるか」——データのライフサイクルで配置を決めます。
| いつ決まるか | 置く場所 |
|---|---|
| 設計時に決まる(不変) | コントロール自身 |
| 画面表示時に決まる | OnVisible |
| 操作中に変わる | イベントハンドラ |
OnVisibleから静的定義を外すことで、OnVisibleの役割は「画面表示時に外部から取得するデータの初期化」に絞られます。何が書かれているかだけでなく、何が書かれていないかによっても、コードの意図は伝わります。
「書き方」を整理し、「何を置くか」を選別する。この両方が揃うことで、OnVisibleは「とりあえず初期化を詰め込む場所」から「画面の依存関係を宣言する場所」に変わっていきます。
シリーズ一覧
- その1:画面のことは画面自身に任せる
- その2:Navigation Contextパターン
- その3:Execution Planパターン
- その4:OnVisibleに全部置かない。データのライフサイクルで配置を決める(本記事)

