How the host app opens a SG mini-app straight onto a page, passes data to it, and how the mini-app reads that data back.
The host app shows a list of orders. The user taps one. Instead of opening the mini-app on its home page, you want it to open directly on the order detail page, already showing that order.
Two things travel from the host to the mini-app:
path — which page to openquery — the data that page needspath must match a page already declared in the pages array, exactly.
{
"pages": [
"pages/index/index",
"pages/order-detail/order-detail"
]
}No leading slash, no file extension. If path does not appear in this list, the mini-app opens on its home page instead, and nothing tells you why.
The host app passes path and query.
'path': 'pages/order-detail/order-detail' // Miniapp will directly move the path page
'query': 'orderId=ORD-1789379008594' // Arrives as query: { orderId: 'ORD-1789379008594' }The runtime routes to path on its own. You do not navigate anywhere — the page just loads, and its onLoad receives the query parameters.
// pages/order-detail/order-detail.js
Page({
data: {
orderId: '',
},
onLoad(options) {
// options = { orderId: 'ORD-1789379008594' }
console.log('onLoad options', JSON.stringify(options));
const orderId = options.orderId || '';
if (!orderId) {
this.setData({ errorMsg: 'No order specified' });
return;
}
this.setData({ orderId: orderId });
this.loadOrder(orderId);
},
loadOrder(orderId) {
ft.request({
url: 'https://api.example.com/orders/' + orderId,
success: (res) => this.setData({ order: res.data }),
fail: (err) => console.log('loadOrder fail', err),
});
},
});A page's options is a flat object of query parameters. It does not contain path:
onLoad(options) {
console.log(options.path); // undefined — always
console.log(options.orderId); // 'ORD-1789379008594'
}So you cannot pass data as a trailing path segment. This does not work:
'path': 'pages/order-detail/order-detail/ORD-1789379008594' // WRONG
The route is not a registered page, and even if it routed, the segment never reaches onLoad. Put your data in query, always.
If you need the launch parameters somewhere other than onLoad — a component, a retry, a page deeper in the stack — read them back instead of threading them through:
const enter = ft.getEnterOptionsSync(); // params of the most recent open console.log(enter.path, enter.query); const launch = ft.getLaunchOptionsSync(); // params of the original cold start console.log(launch.path, launch.query);
Both return { path, query, scene, referrerInfo, ... }, with query as an object.
Wrap them in try / catch — not every host build implements them:
let orderId = '';
try {
const enter = ft.getEnterOptionsSync();
orderId = (enter.query && enter.query.orderId) || '';
} catch (e) {
console.log('getEnterOptionsSync unsupported', e);
}path does not. Always encodeURIComponent the value, or a &, =, #, space or + inside it will break the parse.tabBar page — drops the query string entirelyswitchTab cannot carry parameters. For a tab page, write the value to globalData before navigating and read it in the page's onShow.
query is a string, so anything structured has to be encoded:
// host
'query': 'data=' + Uri.encodeComponent(jsonEncode({'id': 12, 'tab': 'refunds'})),// page
onLoad(options) {
let data = {};
try {
data = JSON.parse(decodeURIComponent(options.data || '{}'));
} catch (e) {
console.log('bad data param', e);
}
console.log(data.id, data.tab);
}Log the raw options at both layers. This takes one minute and tells you which side is at fault:
// app.js
onLaunch(options) {
console.log('LAUNCH', JSON.stringify(options));
},// the page
onLoad(options) {
console.log('ONLOAD', JSON.stringify(options));
},app.json → pagespath matches it exactlyquery is key=value, values encodeURIComponent-edoptions.key in onLoad