こんにちは![]()
![]()
![]()
![]()
本記事はUiPath Coded Appsでルーティングを活用するの続編です。
前回の記事ではUiPath Coded Appsでのルーティングの使い方を解説しました。
今回は、その応用編としてクエリ文字列と動的パラメーターの使い方を解説します。
前回の記事で作ったものに変更を加えていくので、まだご覧になっていない方は前回の記事からご参照ください。
まずはクエリ文字列から解説していきます。
クエリ文字列 編
クエリ文字列とは?
クエリ文字列とはURLの後ろに付与するパラメーターのことです。例えば、https://www.uipath.com/ja?q=coded+appsというURLがあった場合、?の後ろ側の文字列q=coded+appsがクエリ文字列です。(この時、qがKeyでcoded+appがValueのKey-Valueペアとなります。)
検索キーワード(検索ページ)やフィルター(一覧ページ)をURLに埋め込む、といったユースケースがあり、Webアプリにクエリ文字列を利用した機能が実装されていると検索結果やフィルター結果を直接表示できるURLを他ユーザーに共有することができます。
React RouterではuseSearchParamsを使います。
クエリ文字列を取得する画面を作ってみる
./srcの中にProductsList.tsxを作成し、以下を貼り付けます。(今のところファイル名は気にしないでください。後続の実装で意味を持ちます。)
export default function ProductsList() {
return <h1>これはProductsList()です</h1>
}
次に./src/main.tsxを以下に変更します。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { getAppBase } from '@uipath/uipath-typescript'
import { BrowserRouter, Routes, Route, Outlet } from 'react-router'
import './index.css'
import App from './App.tsx'
import ChildPage from './ChildPage.tsx'
import GrandChildPage from './GrandChildPage.tsx'
+ import ProductsList from './ProductsList.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<BrowserRouter basename={getAppBase()}>
<Routes>
<Route path='/' element={<App />} />
<Route path='childpage' element={<Outlet />}>
<Route index element={<ChildPage />} />
<Route path='grandchildpage' element={<GrandChildPage />} />
</Route>
+ <Route path='products' element={<ProductsList />} />
</Routes>
</BrowserRouter>
</StrictMode>,
)
npm run devを実行してhttp://localhost:5173/productsにアクセスしてみましょう。(以後Reactアプリは起動したままで大丈夫です。ファイル変更がリアルタイムで反映されます。)
問題なくルーティングできていますね。ここからクエリ文字列を実装していきます。
クエリ文字列を取得し画面に表示させる
./src/ProductsList.tsxを以下に変更します。
+ import { useSearchParams } from "react-router"
export default function ProductsList() {
+ const [searchParams] = useSearchParams()
- return <h1>これはProductsList()です</h1>
+ return(
+ <>
+ <h1>これはProductsList()です</h1>
+ <h2>クエリ文字列「keyword」は {searchParams.get('keyword')} です。</h2>
+ </>
+ )
}
http://localhost:5173/products?keyword=UiPathにアクセスしてみましょう。
クエリ文字列に設定したkeywordが取得できていますね!(UiPath以外の文字列も入力して試してみてください。)
続いて、画面からクエリ文字列を設定できるようにします。
画面からURLにクエリ文字列を渡す
./src/ProductsList.tsxを以下に変更します。
import { useSearchParams } from "react-router"
export default function ProductsList() {
- const [searchParams] = useSearchParams()
+ const [searchParams, setSearchParams] = useSearchParams()
return(
<>
<h1>これはProductsList()です</h1>
<h2>クエリ文字列「keyword」は {searchParams.get('keyword')} です。</h2>
+ <input
+ type='text'
+ onChange={(event) =>
+ setSearchParams((prev) => {
+ prev.set('input', event.target.value)
+ return prev
+ })
+ }
+ />
</>
)
}
入力ボックスが表示されましたね。
文字を入力してみましょう。
入力ボックスの文字列がクエリ文字列に反映されていますね!便利!!!
・・・
いや、これだと便利さがピンとこないですよね(汗)
実際の活用シーンをイメージしやすいように画面を変えちゃいましょう。
商品一覧ページでクエリ文字列を使いフィルター機能を実装する
まずは架空の商品一覧データを作成しましょう。
./srcの中にdata.tsを作成し以下を貼り付けます。
export const products = [
{
productCode: "DEMO-P001",
productName: "ノートパソコン",
category: "PC",
description:
"持ち運びやすさと処理性能を両立した、社内業務向けの14インチノートパソコンです。",
unitPrice: 128000,
stockQuantity: 12,
stockStatus: "在庫あり"
},
{
productCode: "DEMO-P002",
productName: "デスクトップパソコン",
category: "PC",
description:
"複数の業務アプリケーションを快適に利用できる、省スペース型のデスクトップパソコンです。",
unitPrice: 156000,
stockQuantity: 6,
stockStatus: "在庫あり"
},
{
productCode: "DEMO-P003",
productName: "27インチモニター",
category: "周辺機器",
description:
"文字や画像を鮮明に表示できる、USB-C接続対応の27インチモニターです。",
unitPrice: 42000,
stockQuantity: 0,
stockStatus: "在庫なし"
},
{
productCode: "DEMO-P004",
productName: "ワイヤレスマウス",
category: "周辺機器",
description:
"静音クリックと長時間バッテリーを備えた、左右対称デザインのワイヤレスマウスです。",
unitPrice: 3800,
stockQuantity: 35,
stockStatus: "在庫あり"
}
]
この商品一覧を表示させるため./src/ProductsList.tsxを以下に変えましょう。
import { useSearchParams } from "react-router"
+ import { products } from "./data"
export default function ProductsList() {
const [searchParams, setSearchParams] = useSearchParams()
+ const displayedProducts = products
return(
<>
- <h1>これはProductsList()です</h1>
- <h2>クエリ文字列「keyword」は {searchParams.get('keyword')} です。</h2>
- <input
- type='text'
- onChange={(event) =>
- setSearchParams((prev) => {
- prev.set('input', event.target.value)
- return prev
- })
- }
- />
+ <h1>商品在庫一覧</h1>
+
+ <table>
+ <thead>
+ <tr>
+ <th>商品コード</th>
+ <th>商品名</th>
+ <th>カテゴリ</th>
+ <th>単価</th>
+ <th>在庫数</th>
+ <th>在庫状態</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {displayedProducts.map((product) => (
+ <tr key={product.productCode}>
+ <td>{product.productCode}</td>
+ <td>{product.productName}</td>
+ <td>{product.category}</td>
+ <td>{product.unitPrice}円</td>
+ <td>{product.stockQuantity}</td>
+ <td>{product.stockStatus}</td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
</>
)
}
商品一覧の画面が表示されました。
カテゴリのフィルター機能を追加しましょう。
import { useSearchParams } from "react-router"
import { products } from "./data"
export default function ProductsList() {
const [searchParams, setSearchParams] = useSearchParams()
+ const category = searchParams.get('category') ?? ''
- const displayedProducts = products
+ const displayedProducts = products.filter((product) =>
+ product.category.includes(category)
+ )
return(
<>
<h1>商品在庫一覧</h1>
+ <label>カテゴリフィルター
+ <input
+ type='text'
+ defaultValue={category}
+ onChange={(event) =>
+ setSearchParams({category: event.target.value})
+ }
+ />
+ </label>
<table>
<thead>
<tr>
<th>商品コード</th>
<th>商品名</th>
<th>カテゴリ</th>
<th>単価</th>
<th>在庫数</th>
<th>在庫状態</th>
</tr>
</thead>
<tbody>
{displayedProducts.map((product) => (
<tr key={product.productCode}>
<td>{product.productCode}</td>
<td>{product.productName}</td>
<td>{product.category}</td>
<td>{product.unitPrice}円</td>
<td>{product.stockQuantity}</td>
<td>{product.stockStatus}</td>
</tr>
))}
</tbody>
</table>
</>
)
}
カテゴリフィルターがクエリ文字列に反映されること、商品一覧テーブルがフィルターできているが確認できましたね!
クエリ文字列 編はこれにて完了です。つづいて、動的パラメーターを試していきましょう。
動的パラメーター 編
動的パラメーターとは?
動的パラメーターとはURLのパスの一部を動的に変えて表示させるコンテンツを出し分ける仕組みのことです。
例えば、https://www.uipath.com/ja/blog/uipath-japan-story/devconindia-01とhttps://www.uipath.com/ja/blog/uipath-japan-story/volunteer26-01というURLがあった場合、devconindia-01とvolunteer26-01の部分が異なりますよね?このように同じパスの配下でブログ記事を出し分けたい時などに活躍します。
今回の例では、商品コードを動的パラメーターとして設定し、商品コードに応じた商品詳細ページのURLを作成したいと思います。
React RouterではuseParamsを使います。
下準備として商品詳細ページを作成
./srcの中にProductDetails.tsxを作成し以下を貼り付けます。
import { products } from "./data"
export default function ProductDetails() {
const product = products[0]
return (
<>
<header>
<h1>{product.productCode}: {product.productName}</h1>
<p>{product.description}</p>
</header>
<p>カテゴリ: {product.category}</p>
<p>単価: {product.unitPrice}円</p>
<p>在庫数: {product.stockQuantity}</p>
<p>在庫状態: {product.stockStatus}</p>
</>
)
}
./src/main.tsxに以下を追加します。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { getAppBase } from '@uipath/uipath-typescript'
import { BrowserRouter, Routes, Route, Outlet } from 'react-router'
import './index.css'
import App from './App.tsx'
import ChildPage from './ChildPage.tsx'
import GrandChildPage from './GrandChildPage.tsx'
import ProductsList from './ProductsList.tsx'
+ import ProductDetails from './ProductDetails.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<BrowserRouter basename={getAppBase()}>
<Routes>
<Route path='/' element={<App />} />
<Route path='childpage' element={<Outlet />}>
<Route index element={<ChildPage />} />
<Route path='grandchildpage' element={<GrandChildPage />} />
</Route>
<Route path='products' element={<ProductsList />} />
+ <Route path='products/:productCode' element={<ProductDetails />}/>
</Routes>
</BrowserRouter>
</StrictMode>,
)
Routeのpathに:productCodeという文字列を入れています。パスの中で:から始まる文字列はelementで設定したコンポーネントの中で動的パラメーターとして取得できます。
http://localhost:5173/products/DEMO-P004にアクセスしてみましょう。
画面は無事作られていますが、対象の商品コードのページにはなっていないですね。まだ./src/ProductDetails.tsxに商品データをハードコーディングしているので当然といえば当然ですね。(const product = products[0]の部分)
URLの動的パラメーターを取得し、それに応じた商品を表示できるように変えていきましょう。
動的パラメーターを取得する
./src/ProductDetails.tsxを以下の通りに変えましょう。
+ import { useParams } from "react-router"
import { products } from "./data"
export default function ProductDetails() {
+ const params = useParams()
- const product = products[0]
+ const product = products.find((product) =>
+ product.productCode === params.productCode
+ ) ?? products[0]
return (
<>
<header>
<h1>{product.productCode}: {product.productName}</h1>
<p>{product.description}</p>
</header>
<p>カテゴリ: {product.category}</p>
<p>単価: {product.unitPrice}円</p>
<p>在庫数: {product.stockQuantity}</p>
<p>在庫状態: {product.stockStatus}</p>
</>
)
}
useParams()で取得したparamsの中の値はRouteで設定した動的パラメーターを指定することで取得できます。先ほど./src/main.tsxで<Route path='products/:productCode' element={<ProductDetails />}/>と書きました。この:productCodeがパラメーターになりますので、params.productCodeで値を取得できます。
改めてhttp://localhost:5173/products/DEMO-P004にアクセスしてみましょう。
商品コードDEMO-P004のデータが取得できていますね。
次にhttp://localhost:5173/products/DEMO-P002にもアクセスしてみましょう。
こちらも無事にDEMO-P002のデータが取得できていますね!
[おまけ] 商品一覧ページから商品詳細ページに飛べるようにする
今回の解説としては特に重要ではないですが、より実際の使い方に近づけるために商品一覧ページの商品名をクリックすると商品詳細ページに飛べるように修正しておきましょう。
./src/ProductsList.tsxを以下に修正します。
- import { useSearchParams } from "react-router"
+ import { Link, useSearchParams } from "react-router"
import { products } from "./data"
export default function ProductsList() {
const [searchParams, setSearchParams] = useSearchParams()
const category = searchParams.get('category') ?? ''
const displayedProducts = products.filter((product) =>
product.category.includes(category)
)
return(
<>
<h1>商品在庫一覧</h1>
<label>カテゴリフィルター
<input
type='text'
defaultValue={category}
onChange={(event) =>
setSearchParams({category: event.target.value})
}
/>
</label>
<table>
<thead>
<tr>
<th>商品コード</th>
<th>商品名</th>
<th>カテゴリ</th>
<th>単価</th>
<th>在庫数</th>
<th>在庫状態</th>
</tr>
</thead>
<tbody>
{displayedProducts.map((product) => (
<tr key={product.productCode}>
<td>{product.productCode}</td>
- <td>{product.productName}</td>
+ <Link to={`/products/${product.productCode}`}>
+ <td>{product.productName}</td>
+ </Link>
<td>{product.category}</td>
<td>{product.unitPrice}円</td>
<td>{product.stockQuantity}</td>
<td>{product.stockStatus}</td>
</tr>
))}
</tbody>
</table>
</>
)
}
http://localhost:5173/productsにアクセスして各商品詳細ページに飛んでみましょう。
無事にクリックした商品の詳細ページに飛べましたね!!
UiPath Coded Appsとしてデプロイする
前回と同様にUiPath Coded Appsとしてデプロイしてみましょう。
uip login
npm run build
uip codedapp pack dist -n {アプリ名(今回はmy-app)} --version 2.0.0
uip codedapp publish
uip codedapp deploy
デプロイ後にもクエリ文字列、動的パラメーターが問題なく機能していますね!
おわりに
前回と合わせて一通りルーティングの機能がご説明できたと思います。
UiPath Coded Appsをご利用の際は、ぜひReact Routerを活用してユーザーフレンドリーなアプリ開発に役立てていただければと思います。














