共通機能
コンテキストオブジェクトは NocoBase の各種組み込み機能を提供します。ただし、一部の機能は Plugin でのみ利用可能、一部はコンポーネントでのみ利用可能、一部は両方で使えるが書き方が異なります。まず一覧を確認しましょう:
以下、namespace ごとに紹介します。
API リクエスト(ctx.api)
ctx.api.request() でバックエンド API を呼び出します。使い方は Axios と同じです。
Plugin 内での使用
import { Plugin } from '@nocobase/client-v2';
class MyPlugin extends Plugin {
async load() {
// load() 内で直接リクエストを送信
const response = await this.context.api.request({
url: 'app:getInfo',
method: 'get',
});
console.log('アプリケーション情報', response.data);
}
}
コンポーネント内での使用
import { useFlowContext } from '@nocobase/flow-engine';
export default function MyPage() {
const ctx = useFlowContext();
const handleLoad = async () => {
// GET リクエスト
const response = await ctx.api.request({
url: 'users:list',
method: 'get',
});
console.log(response.data);
// POST リクエスト
await ctx.api.request({
url: 'users:create',
method: 'post',
data: { name: 'Tao Tao' },
});
};
return <button onClick={handleLoad}>データを読み込む</button>;
}
ahooks useRequest との併用
コンポーネント内では、ahooks の useRequest を使ってリクエストの状態管理を簡素化できます:
import { useFlowContext } from '@nocobase/flow-engine';
import { useRequest } from 'ahooks';
export default function PostList() {
const ctx = useFlowContext();
const { data, loading, error, refresh } = useRequest(() =>
ctx.api.request({
url: 'posts:list',
method: 'get',
}),
);
if (loading) return <div>読み込み中...</div>;
if (error) return <div>リクエストエラー: {error.message}</div>;
return (
<div>
<button onClick={refresh}>更新</button>
<pre>{JSON.stringify(data?.data, null, 2)}</pre>
</div>
);
}
リクエストインターセプター
ctx.api.axios を通じてリクエスト / レスポンスのインターセプターを追加できます。通常は Plugin の load() 内で設定します:
async load() {
// リクエストインターセプター:カスタムヘッダーを追加
this.context.api.axios.interceptors.request.use((config) => {
config.headers['X-Custom-Header'] = 'my-value';
return config;
});
// レスポンスインターセプター:統一エラー処理
this.context.api.axios.interceptors.response.use(
(response) => response,
(error) => {
console.error('リクエストエラー', error);
return Promise.reject(error);
},
);
}
NocoBase カスタムリクエストヘッダー
NocoBase Server は以下のカスタムリクエストヘッダーをサポートしています。通常はインターセプターによって自動注入されるため、手動で設定する必要はありません:
国際化(ctx.t / ctx.i18n)
NocoBase プラグインは src/locale/ ディレクトリで多言語ファイルを管理し、ctx.t() でコード内から翻訳を使用します。
多言語ファイル
プラグインの src/locale/ 配下に言語ごとの JSON ファイルを作成します:
plugin-hello/
└── src/
└── locale/
├── zh-CN.json
└── en-US.json
// zh-CN.json
{
"Hello": "你好",
"Your name is {{name}}": "你的名字是 {{name}}"
}
// en-US.json
{
"Hello": "Hello",
"Your name is {{name}}": "Your name is {{name}}"
}
注意
初めて言語ファイルを追加した場合、アプリの再起動が必要です。
ctx.t()
コンポーネント内で ctx.t() を使って翻訳テキストを取得します:
const ctx = useFlowContext();
// 基本的な使い方
ctx.t('Hello');
// 変数付き
ctx.t('Your name is {{name}}', { name: 'NocoBase' });
// 名前空間を指定(デフォルトの名前空間はプラグインのパッケージ名)
ctx.t('Hello', { ns: '@my-project/plugin-hello' });
this.t()
Plugin 内では this.t() がより便利です — プラグインのパッケージ名を namespace として自動注入するため、手動で ns を渡す必要がありません:
class MyPlugin extends Plugin {
async load() {
// 自動的に現在のプラグインのパッケージ名を ns として使用
console.log(this.t('Hello'));
// 以下と同等
console.log(this.context.t('Hello', { ns: '@my-project/plugin-hello' }));
}
}
ctx.i18n
ctx.i18n は基盤となる i18next インスタンスです。通常は ctx.t() だけで十分ですが、動的な言語切り替えや言語変更の監視などが必要な場合は ctx.i18n を使います:
// 現在の言語を取得
const currentLang = ctx.i18n.language; // 'zh-CN'
// 言語変更を監視
ctx.i18n.on('languageChanged', (lng) => {
console.log('言語が変更されました', lng);
});
tExpr()
tExpr() は遅延翻訳の式文字列を生成するために使います。通常は FlowModel.define() 内で使用します — define はモジュール読み込み時に実行されますが、この時点では i18n インスタンスがまだ存在しないためです:
import { tExpr } from '@nocobase/flow-engine';
HelloBlockModel.define({
label: tExpr('Hello block'), // '{{t("Hello block")}}' を生成し、ランタイムで翻訳
});
より完全な国際化の使い方(翻訳ファイルの書き方、useT hook、tExpr など)は i18n 国際化をご覧ください。NocoBase がサポートする言語コードの完全なリストは言語一覧をご覧ください。
ログ(ctx.logger)
ctx.logger で構造化ログを出力します。pino ベースです。
Plugin 内での使用
import { Plugin } from '@nocobase/client-v2';
class MyPlugin extends Plugin {
async load() {
this.context.logger.info('プラグインの読み込み完了', { plugin: 'my-plugin' });
this.context.logger.error('初期化に失敗', { error });
}
}
コンポーネント内での使用
import { useFlowContext } from '@nocobase/flow-engine';
export default function MyPage() {
const ctx = useFlowContext();
const handleLoad = async () => {
ctx.logger.info('ページの読み込み完了', { page: 'UserList' });
ctx.logger.debug('現在のユーザー状態', { user });
};
// ...
}
ログレベルは高い順に:fatal > error > warn > info > debug > trace。現在の設定レベル以上のログのみが出力されます。
ルーティング(ctx.router / ctx.route / ctx.location)
ルーティング関連の機能は3つの部分に分かれます:登録(Plugin のみ)、ナビゲーション、情報取得(コンポーネントのみ)。
ルート登録(this.router / this.pluginSettingsManager)
Plugin の load() 内で this.router.add() によりページルートを登録し、this.pluginSettingsManager によりプラグイン設定ページを登録します:
async load() {
// 通常のページルートを登録
this.router.add('hello', {
path: '/hello',
componentLoader: () => import('./pages/HelloPage'),
});
// プラグイン設定ページを登 録(「プラグイン設定」メニューに表示される)
this.pluginSettingsManager.addMenuItem({
key: 'my-settings',
title: this.t('My Settings'),
icon: 'SettingOutlined', // Ant Design アイコン。参考:https://5x.ant.design/components/icon
});
this.pluginSettingsManager.addPageTabItem({
menuKey: 'my-settings',
key: 'index',
title: this.t('My Settings'),
componentLoader: () => import('./pages/MySettingsPage'),
});
}
詳しい使い方は Router ルーティングをご覧ください。完全な設定ページの例はプラグイン設定ページを作るをご覧ください。
注意
this.router は RouterManager で、ルートの登録に使います。this.pluginSettingsManager は PluginSettingsManager で、設定ページの登録に使います。これらはコンポーネント内の ctx.router(React Router、ページナビゲーションに使用)とは別のものです。
ページナビゲーション(ctx.router)
コンポーネント内で ctx.router.navigate() を使ってページ遷移します:
const ctx = useFlowContext();
ctx.router.navigate('/hello'); // -> /v/hello
ルート情報(ctx.route)
コンポーネント内で ctx.route から現在のルート情報を取得します:
const ctx = useFlowContext();
// 動 的パラメータの取得(例:ルート定義が /users/:id の場合)
const { id } = ctx.route.params;
// ルート名の取得
const { name } = ctx.route;
ctx.route の完全な型:
interface RouteOptions {
name?: string; // ルートの一意識別子
path?: string; // ルートテンプレート
pathname?: string; // ルートの完全パス
params?: Record<string, any>; // ルートパラメータ
}
現在の URL(ctx.location)
ctx.location は現在の URL の詳細情報を提供します。ブラウザの window.location に似ています:
const ctx = useFlowContext();
console.log(ctx.location.pathname); // '/v/hello'
console.log(ctx.location.search); // '?page=1'
console.log(ctx.location.hash); // '#section'
ctx.route と ctx.location は Plugin 内でも this.context 経由でアクセスできますが、プラグイン読み込み時の URL は不定であるため、取得した値に意味はありません。コンポーネント内での使用をお勧めします。
ビュー管理(ctx.viewer / ctx.view)
ctx.viewer はダイアログやドロワーなどのビューを命令的に開く機能を提供します。Plugin とコンポーネントの両方で使用できます。
Plugin 内での使用
import { Plugin } from '@nocobase/client-v2';
class MyPlugin extends Plugin {
async load() {
// 初期化ロジック内でダイアログを開く例
this.context.viewer.dialog({
title: 'ようこそ',
content: () => <div>プラグインの初期化が完了しました</div>,
});
}
}
コンポーネント内での使用
import { Button } from 'antd';
import { useFlowContext } from '@nocobase/flow-engine';
export default function MyPage() {
const ctx = useFlowContext();
const openDetail = () => {
// ダイアログを開く
ctx.viewer.dialog({
title: 'ユーザー編集',
content: () => <UserEditForm />,
});
};
const openDrawer = () => {
// ドロワーを開く
ctx.viewer.drawer({
title: '詳細',
content: () => <UserDetail />,
});
};
return (
<div>
<Button onClick={openDetail}>編集</Button>
<Button onClick={openDrawer}>詳細を表示</Button>
</div>
);
}
汎用メソッド
// type でビュータイプを指定
ctx.viewer.open({
type: 'dialog', // 'dialog' | 'drawer' | 'popover' | 'embed'
title: 'タイトル',
content: () => <SomeComponent />,
});
ビュー内部での操作(ctx.view)
ダイアログ / ドロワー内部のコンポーネントでは、ctx.view を使って現在のビューを操作できます(例:閉じる):
import { Button } from 'antd';
import { useFlowContext } from '@nocobase/flow-engine';
function DialogContent() {
const ctx = useFlowContext();
return (
<div>
<p>ダイアログの内容</p>
<Button onClick={() => ctx.view.close()}>閉じる</Button>
</div>
);
}