RORK LABJP
BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verifyBUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify
Articles/Dev Tools
Dev Tools/2026-06-23Intermediate

What Your App Should Do When Someone Turns On Reduce Motion — A Motion-Respecting Layer in Expo

When a user enables iOS Reduce Motion or Android Remove Animations, how should your app respond? Combine AccessibilityInfo with Reanimated's ReduceMotion to replace heavy motion with a calmer alternative instead of simply switching it off.

Reduce Motion2Accessibility4Reanimated10Expo175React Native227

Premium Article

One day a review on a wallpaper app I maintain included a single line: "the slideshow makes me feel sick." Three stars. The note was short, but as an indie developer I sat with it for a while. The transition I had built as a cross-fade actually layered in a slight zoom and some parallax. For someone with Reduce Motion enabled, that movement was not pleasant — it was a burden.

When you run several apps in parallel on your own, you keep discovering this kind of "bug you can't see from your own device." Reduce Motion was a textbook case. Users with the setting on certainly exist, and our animations were reaching them too forcefully.

This article walks through how to build a layer that returns a gentler alternative based on the user's setting — not one that strips animation away wholesale — following an Expo + Reanimated implementation.

Where the device tells you about Reduce Motion

First, let's pin down how the OS exposes this preference.

On iOS it lives under Settings → Accessibility → Motion → Reduce Motion. On Android the closest equivalent is Settings → Accessibility → Remove animations. From React Native, both are read through the same AccessibilityInfo API.

import { AccessibilityInfo } from 'react-native';
 
// Read the current state once
const enabled = await AccessibilityInfo.isReduceMotionEnabled();

The easy thing to miss is that isReduceMotionEnabled() is an asynchronous API returning Promise<boolean>. You'll be tempted to read it synchronously, but the value isn't settled on the first render. Worse, users sometimes toggle the setting while your app is open — they jump to Settings, turn it on, and come back. To follow that round trip you need a subscription, not a one-time read.

A useReducedMotion hook that follows mid-session changes

You can subscribe to changes with AccessibilityInfo.addEventListener('reduceMotionChanged', ...). Let's wrap it in a small hook.

import { useEffect, useState } from 'react';
import { AccessibilityInfo } from 'react-native';
 
export function useReducedMotion(): boolean {
  const [reduced, setReduced] = useState(false);
 
  useEffect(() => {
    let mounted = true;
 
    // Read the initial value (async, so handle it with then, not await)
    AccessibilityInfo.isReduceMotionEnabled().then((value) => {
      if (mounted) setReduced(value);
    });
 
    // Follow toggles made while the app is running
    const sub = AccessibilityInfo.addEventListener(
      'reduceMotionChanged',
      (value) => setReduced(value),
    );
 
    return () => {
      mounted = false;
      sub.remove();
    };
  }, []);
 
  return reduced;
}

The mounted flag is there so that if the component unmounts before isReduceMotionEnabled() resolves, the later setReduced never fires. It's a small move, but it quietly prevents warnings on short-lived screens.

Note that since v3.5 Reanimated ships an official useReducedMotion() hook of the same name. If you already use Reanimated, reaching for that is the straightforward choice. I'm showing the hand-rolled version because understanding the mechanism lets you explain to yourself why the first value is false and why toggles are reflected.

// If you already use Reanimated, this is enough
import { useReducedMotion } from 'react-native-reanimated';

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
A useReducedMotion hook that subscribes to AccessibilityInfo and follows changes made while the app is running
Using Reanimated's ReduceMotion.System to tune behavior per animation
A decision table for replacing only parallax and large motion, rather than killing everything
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

Dev Tools2026-06-22
Build a Toast System in Your Rork App That Survives Overlaps, Screen Readers, and Notches
When you add toast notifications to a React Native app generated by Rork, the naive version breaks in three places: two toasts overlap, screen readers stay silent, and the text hides under the notch or home indicator. This walks through a root-level queue, animations decoupled from your app tree, AccessibilityInfo announcements, and safe-area placement — all in working code.
Dev Tools2026-08-17
When an Expo UI drop-in swap actually removes a dependency
Expo UI went stable in SDK 56 with drop-in replacements for eight community packages. Swapping one import does not always shrink your dependency list. Here is how to decide which swaps actually pay off, straight from the dependency graph.
Dev Tools2026-08-16
Find the Code That Trips App Store 2.5.2 Before You Submit
If a remote value can change what your app does, Guideline 2.5.2 may apply. Here is where the line actually sits, plus a script that surfaces the risky paths in your repo before submission.
📚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 →