youzan/vant-weapp · warning

未找到 van-toast 节点,请确认 selector 及 context 是否正确

Error message

未找到 van-toast 节点,请确认 selector 及 context 是否正确

What it means

This warning is emitted by Vant Weapp's Toast() (also via the createMethod shortcuts Toast.loading/Toast.success/Toast.fail, which call the same function) when context.selectComponent(options.selector) cannot find a <van-toast> component instance. The imperative Toast API only configures and shows an existing <van-toast id="van-toast"> node declared in WXML; if it can't be resolved, the library warns and returns undefined instead of showing the toast, and any returned-instance chaining fails.

Source

Thrown at packages/toast/toast.ts:61

function getContext() {
  const pages = getCurrentPages();
  return pages[pages.length - 1];
}

function Toast(toastOptions: ToastOptions | ToastMessage) {
  const options = {
    ...currentOptions,
    ...parseOptions(toastOptions),
  } as ToastOptions;

  const context =
    (typeof options.context === 'function'
      ? options.context()
      : options.context) || getContext();
  const toast = context.selectComponent(options.selector as string);

  if (!toast) {
    console.warn('未找到 van-toast 节点,请确认 selector 及 context 是否正确');
    return;
  }

  delete options.context;
  delete options.selector;

  toast.clear = () => {
    toast.setData({ show: false });

    if (options.onClose) {
      options.onClose();
    }
  };

  queue.push(toast);
  toast.setData(options);
  clearTimeout(toast.timer);

View on GitHub (pinned to 7a7d43757e)

Solutions

  1. Add <van-toast id="van-toast" /> to the WXML of every page (or the containing component) that uses the imperative Toast API, and register the component in the page JSON.
  2. If the node is in a child component, pass options.context: () => this.selectComponent('#child') (or the instance) so selectComponent searches the right subtree.
  3. If you renamed the node, pass the matching selector, e.g. Toast.success({ selector: '#my-toast', message: 'ok' }).
  4. Call Toast only from page/component code after the page has rendered (e.g. onReady or later event handlers), not from App.onLaunch.
  5. Guard on the return value: Toast returns the instance on success and undefined here — check it before calling instance-based APIs like toast.clear().

Example fix

// before
Toast.loading({ message: 'Loading...', context: this.selectComponent('#child') }); // node lives in child but selectComponent called on child's own scope may miss/wrong scope
// after
Toast.loading({ message: 'Loading...', context: () => this.selectComponent('#child') });
// and page.wxml (or child wxml) contains:
// <van-toast id="van-toast" />
Defensive patterns

Strategy: validation

Validate before calling

function assertToastNode(context?: (() => object) | object, selector = '#van-toast') {
  const ctx =
    (typeof context === 'function' ? context() : context) ||
    getCurrentPages()[getCurrentPages().length - 1];
  if (!ctx || typeof ctx.selectComponent !== 'function' || !ctx.selectComponent(selector)) {
    throw new Error(
      `<van-toast ${selector}> not found. Add <van-toast id="van-toast" /> to the page WXML and register it in usingComponents.`
    );
  }
}
// call before Toast()/Toast.loading etc:
// assertToastNode(() => this.selectComponent('#child'));

Type guard

function isToastInstance(v: unknown): v is { clear(): void; setData(d: object): void; timer?: number } {
  return !!v && typeof (v as any).clear === 'function';
}

Try / catch

try {
  const toast = Toast.loading({ message: 'Loading...', context: () => this.selectComponent('#child') });
  if (!isToastInstance(toast)) {
    throw new Error('van-toast node not found; check selector/context');
  }
} catch (e) {
  console.warn('Toast failed:', e);
  wx.showLoading({ title: 'Loading' }); // native fallback
}

Prevention

When it happens

Trigger: Calling Toast('msg') or Toast.loading/success/fail when (1) the page WXML lacks <van-toast id="van-toast" />, (2) options.selector is set to a custom id that doesn't exist in the resolved context, (3) options.context (instance or () => instance) resolves to a page/component that doesn't directly contain the <van-toast> node, or (4) the call happens while getCurrentPages() is empty or before the page tree is available, so the fallback getContext() yields nothing useful.

Common situations: Calling Toast from a shared utility/service module while the toast node was added to only some pages; forgetting to add <van-toast id="van-toast" /> to a newly created page that imports the imperative API; declaring the node inside a custom component and calling Toast.success from the page without passing context: () => this.selectComponent('#child'); giving the node a different id (e.g. id="toast") while keeping the default selector '#van-toast'; calling Toast during onLaunch/App-level code before any page exists.

Related errors


AI-assisted analysis of youzan/vant-weapp@7a7d43757e (2026-09-02). Data as JSON: /api/errors/51e1a1e758bac5ee. Report an issue: GitHub.