より高度なユースケースでは、アプリケーションの別の部分からUploaderをトリガーしたり、プログラムでその動作を制御したりする必要があるかもしれません。UploaderProvider コンポーネントとそれに関連するフックは、ReactのContext APIを使用して、UploaderのUIをそのトリガーから分離する柔軟な方法を提供します。
このパターンは、ヘッダーのボタン、メニューのリンク、またはUploader自体の直接の子ではない任意の要素からUploaderモーダルを開きたい場合に最適です。
このアプローチには、主に3つの部分が含まれます。
UploaderProvider
Uploaderをインスタンス化し、コンテキストを介してそのインスタンスを提供するラッパーコンポーネント。
UploaderTrigger
Uploaderモーダルを開くためのクリック可能な領域を作成するシンプルなコンポーネント。
useUploaderContext
カスタムロジックのためにUploaderインスタンスに直接アクセスするためのフック。
仕組み
UploaderProviderは<Uploader />コンポーネントをレンダリングし(多くの場合、ドキュメントボディにアタッチされたポータル内で)、そのインスタンスへの参照(ref)を保持します。プロバイダーのツリー内の任意の子コンポーネントは、useUploaderContextフックを使用してこのrefにアクセスできます。UploaderTriggerは、このフックを使用してUploaderインスタンスのopen()メソッドを呼び出す、事前に構築されたコンポーネントです。
UploaderProvider
このコンポーネントは、このパターンの基盤です。Uploaderと対話する必要があるすべてのコンポーネント(UploaderTriggerやuseUploaderContextフックを使用するカスタムコンポーネントを含む)をラップする必要があります。
これは<Uploader />コンポーネントと同じすべてのプロップを受け入れ、Uploaderの動作、プラグイン、外観を設定できます。このパターンでは、ほとんどの場合popup={true}を設定することになります。
プロップ
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Uploaderコンテキストにアクセスできる子コンポーネント。 |
popup | boolean | trueの場合、UploaderはReact Portalを使用してモーダルでレンダリングされます。falseの場合、インラインでレンダリングされます。デフォルトはtrueです。 |
...restProps | UploaderProps | 他のすべてのプロップは、基になる<Uploader />コンポーネントに直接渡されます。完全なリストについては、Uploader Component Props を参照してください。 |
使用方法
アプリケーションの一部、またはアプリケーション全体をUploaderProviderでラップします。
MyUploader.jsx
import React from 'react';
import { UploaderProvider, UploaderTrigger } from '@blocklet/uploader/react';
import Button from '@mui/material/Button';
export default function MyUploader() {
const handleUploadSuccess = (result) => {
console.log('Files uploaded: ', result);
// resultには、ファイルオブジェクトの{ successful, failed }配列が含まれます
};
return (
<UploaderProvider endpoint="/api/upload" popup={true}>
<UploaderTrigger onChange={handleUploadSuccess}>
<Button variant="contained">Upload File</Button>
</UploaderTrigger>
{/* アプリ内の他のコンポーネントもここに配置できます */}
</UploaderProvider>
);
}UploaderTrigger
UploaderTriggerコンポーネントは、その子要素をクリック可能にし、Uploaderモーダルを開くトリガーとなる便利なラッパーです。
プロップ
| Prop | Type | Description |
|---|---|---|
children | ReactNode | トリガーとして使用するReact要素(<Button>や<a>タグなど)。 |
onChange | Function | アップロードが成功した後に一度だけトリガーされるオプションのコールバック関数。Uppyからの結果オブジェクトを受け取ります。 |
...restProps | object | 追加のプロップは、基になるMaterial-UIの<Box>コンポーネントに渡されます。 |
使用方法
クリック可能なコンポーネントをUploaderTrigger内に配置します。onChangeプロップは、アップロードの結果を処理する簡単な方法を提供します。
<UploaderTrigger onChange={(result) => alert(`Uploaded ${result.successful.length} files!`)}>
<Button>Click me to Upload</Button>
</UploaderTrigger>useUploaderContext
最大限の制御を行うために、useUploaderContextフックはUploaderのインスタンスrefへの直接アクセスを提供します。これにより、Uploaderまたはその基になるUppyインスタンスの任意のメソッドをプログラムで呼び出すことができます。
戻り値
| Value | Type | Description |
|---|---|---|
uploaderRef | React.RefObject | Reactのrefオブジェクト。UploaderインスタンスはuploaderRef.currentにあります。Uppyインスタンスにアクセスするには、uploaderRef.current.getUploader()を使用します。 |
注: このフックは、
UploaderProviderの子孫ではないコンポーネントで使用されるとエラーをスローします。
使用方法
以下は、フックを使用してUploaderを開き、現在選択されているファイルの数をログに記録するカスタムコンポーネントの例です。
CustomControls.jsx
import React from 'react';
import { useUploaderContext } from '@blocklet/uploader/react';
import Button from '@mui/material/Button';
import Box from '@mui/material/Box';
export default function CustomControls() {
const uploaderRef = useUploaderContext();
const handleOpenUploader = () => {
const uploader = uploaderRef?.current?.getUploader();
uploader?.open();
};
const handleLogFiles = () => {
const uploader = uploaderRef?.current?.getUploader();
const files = uploader?.getFiles();
console.log('Current files in Uppy:', files);
alert(`There are ${files.length} files selected.`);
};
return (
<Box sx={{ display: 'flex', gap: 2, mt: 2 }}>
<Button variant="outlined" onClick={handleOpenUploader}>
Open Uploader Manually
</Button>
<Button variant="outlined" color="secondary" onClick={handleLogFiles}>
Log Current Files
</Button>
</Box>
);
}このCustomControlsコンポーネントを使用するには、次のようにUploaderProvider内に配置します。
App.jsx
// ... インポート
import CustomControls from './CustomControls';
export default function App() {
return (
<UploaderProvider endpoint="/api/upload">
{/* プライマリートリガーをそのまま使用することもできます */}
<UploaderTrigger>
<Button>Upload</Button>
</UploaderTrigger>
{/* そして、より多くの制御のためにカスタムコンポーネントも使用できます */}
<CustomControls />
</UploaderProvider>
);
}このパターンは高度な柔軟性を提供し、アップローダーを複雑なアプリケーションレイアウトやワークフローにシームレスに統合することができます。
次に、一般的なタスクを簡素化できるヘルパー関数をいくつか見てみましょう。