RORK LABJP
ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029ENGINE — Rork Max is powered by Claude Code and Claude Opus 4.6, generating native Swift apps directlyCORE ML — Rork Max reaches on-device Core ML inference alongside HealthKit, HomeKit, NFC, and App ClipsSEED — Rork raised a $15M seed led by Left Lane Capital in April 2026, joined by Peak XV and a16z SpeedrunM&A — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026GROWTH — The no-code AI platform market is projected to grow from $4.9B in 2024 to $24.8B by 2029
Articles/App Dev
App Dev/2026-06-29Intermediate

Clipboard UX in Expo apps — copy and paste without flooding users with iOS's paste banner

When you wire up copy and paste with expo-clipboard, iOS's paste permission banner can fire constantly and quietly erode trust. Here's exactly when the banner appears, and how hasStringAsync lets you gate a Paste button without ever reading the contents.

Rork498Expo139ClipboardiOS107UX Design9

Premium Article

When I added an invite-code redemption screen to one of my wallpaper apps, a small banner reading "Pasted from [other app]" appeared at the top of the screen every single time the screen opened. Testers kept asking me, "Is this actually safe?" The cause was obvious in hindsight: trying to be helpful, I was reading the clipboard the moment the screen mounted and auto-filling the code field. The instant you read, that banner fires.

Clipboard integration looks like a trivial feature — copy one line of text — but without understanding iOS's behavior, it quietly turns your app into a noisy one. Let me walk through how to use expo-clipboard so the paste banner only shows when it makes sense, while copy and paste still feel smooth.

Where the paste banner actually comes from

This trips people up: copying (writing) and pasting (reading) are treated completely differently.

Writing — Clipboard.setStringAsync() — produces no notification at all. It happens because the user pressed a copy button, so that's expected. The reading side is where the trouble is. Since iOS 16, reading content another app copied via Clipboard.getStringAsync() shows a "Pasted from [app]" banner. It exists to tell the user "this app just peeked at your clipboard," and you cannot turn it off.

This is why when you read matters so much. My mistake was reading before the user had done anything — on mount. A read that happens right after the user taps "Paste" produces a banner that matches the context, so it doesn't feel intrusive. A read on open, or on a polling interval, fires banners the user can't account for, and that breeds suspicion.

ActionAPIiOS banner
Copy (write)setStringAsync()No
Read contents (paste)getStringAsync()Yes (iOS 16+)
Check presence onlyhasStringAsync()No

Use hasStringAsync to gate the button without reading

That last row is the key. hasStringAsync() returns a boolean for "is there a string on the clipboard" without ever reading the contents — so no banner. With it, you can disable the Paste button when the clipboard is empty and enable it only when something is there. You read the actual value only at the moment the user taps that button.

import { useEffect, useState } from "react";
import * as Clipboard from "expo-clipboard";
 
function RedeemCodeField({ onPaste }: { onPaste: (value: string) => void }) {
  const [canPaste, setCanPaste] = useState(false);
 
  // Checks presence only — never reads contents, so no banner
  useEffect(() => {
    let mounted = true;
    Clipboard.hasStringAsync().then((has) => {
      if (mounted) setCanPaste(has);
    });
    return () => {
      mounted = false;
    };
  }, []);
 
  // The real read happens only when the user taps the button
  const handlePaste = async () => {
    const text = await Clipboard.getStringAsync();
    if (text) onPaste(text.trim());
  };
 
  return (
    <PasteButton disabled={!canPaste} onPress={handlePaste} />
  );
}

Calling hasStringAsync() once on mount produces no banner. If you also want to re-check when the app returns to the foreground, call hasStringAsync() again from the AppState change event when state becomes active. You're still only checking presence, so it stays safe.

For something with a fixed shape like an invite code, don't drop the pasted string in verbatim. Run text.trim() to strip surrounding whitespace, then do a light validation against the expected format before applying it. That way the field doesn't break when a user accidentally copies extra characters along with the code.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
The exact conditions that trigger iOS's paste permission banner, and how to offer paste without multiplying it
An implementation pattern that uses hasStringAsync to enable a Paste button without reading the clipboard
Reliable copy feedback, plus how to clean up after putting sensitive data on the clipboard
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

App Dev2026-07-05
Building a One-Time Code Field in Expo — SMS Autofill and Segmented Display Together
A six-digit verification screen looks trivial, but once you account for SMS autofill, pasting, and deleting one digit at a time, it needs real care. Here is how to nail the iOS and Android autofill first, then build a segmented look on top of a single TextInput that does not break.
App Dev2026-06-27
Before You Ask 'Are You Sure?' — Consider an Undoable Delete
Showing a confirmation dialog every time someone removes a list item trains them to tap OK without reading. Here is how to build an undoable delete in a Rork (Expo) app, and where confirmation dialogs still belong.
App Dev2026-07-07
Laying Out Variable-Height Images in Two Columns: A Masonry Wallpaper Gallery in a Rork Expo App
From why numColumns cannot pack variable-aspect images cleanly, to a dependency-free column-balancing algorithm, to keeping virtualization with FlashList masonry and a pragmatic no-dependency fallback, building a wallpaper gallery with real code.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →