@vapng/react-native-wheel
v1.1.7
Published
High-performance React Native Wheel of Fortune spinner with Reanimated 60fps animations, SVG & Skia renderers, weighted probability, and controlled winner mode
Maintainers
Readme
@vapng/react-native-wheel — React Native Wheel of Fortune Spinner
A high-performance, fully customizable Wheel of Fortune / Spinning Wheel component for React Native (iOS, Android, Web). Powered by react-native-reanimated for 60 fps UI-thread animations and react-native-svg, with optional @shopify/react-native-skia GPU rendering.
Short demo

Full demo

Features
- 🎯 Deterministic — controlled mode guarantees exactly which segment the wheel lands on
- ⚡ Performant — 60 fps animations via Reanimated UI-thread worklets, zero JS-bridge overhead
- 🖼 Multiple Renderers — SVG (default, widest support) or Skia (GPU-accelerated)
- 🎨 Highly Customizable — themes, custom segment slices, images, pointers, labels, and center overlays
- ⚖️ Flexible Winner Modes — random, weighted probability, or exact controlled outcome
- ♿ Accessible —
accessibilityRole,accessibilityState, and winner announcements viaAccessibilityInfo - 🌐 Cross-platform — iOS, Android, and Web
Platform Support
| Platform | Supported | Notes | |----------|-----------|-------| | iOS | ✅ | Fully supported | | Android | ✅ | Fully supported | | Web | ✅ | SVG renderer only |
Installation
yarn add @vapng/react-native-wheel \
react-native-reanimated \
react-native-svg \
react-native-gesture-handlerFollow the native setup guides for each peer dependency:
Optional — Skia renderer:
yarn add @shopify/react-native-skiaQuick Start
import React, { useRef } from 'react';
import { View, Button } from 'react-native';
import { Wheel, type WheelRef } from '@vapng/react-native-wheel';
const DATA = [
{ id: '1', label: '🎁 Grand Prize', color: '#E8413E' },
{ id: '2', label: '💰 Cash', color: '#3E7BFA' },
{ id: '3', label: '🎟 Ticket', color: '#44C97B' },
{ id: '4', label: '😢 Try Again', color: '#F5A623' },
];
export default function App() {
const wheelRef = useRef<WheelRef>(null);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Wheel
ref={wheelRef}
data={DATA}
size={300}
onSpinEnd={(winner) => console.log('Winner:', winner.label)}
/>
<Button title="SPIN" onPress={() => wheelRef.current?.spin()} />
</View>
);
}Winner Modes
1. Random (default)
<Wheel data={data} onSpinEnd={(w) => console.log(w.label)} />
// wheelRef.current.spin()2. Weighted
const data = [
{ id: '1', label: 'Rare', color: '#red', weight: 1 },
{ id: '2', label: 'Common', color: '#green', weight: 9 },
];
<Wheel data={data} weighted onSpinEnd={(w) => console.log(w.label)} />Common will win approximately 90% of the time.
3. Controlled (guaranteed outcome)
<Wheel
data={data}
controlledWinnerId="1" // will always land on id '1'
onSpinEnd={(w) => console.log(w.label)}
/>Ref API
Attach a ref to control the wheel imperatively:
const wheelRef = useRef<WheelRef>(null);
<Wheel ref={wheelRef} data={data} />;| Method | Signature | Description |
|--------|-----------|-------------|
| spin | () => void | Spin using the current winner mode |
| spinTo | (id: string) => void | Force spin to land on a specific item ID |
| reset | () => void | Instantly reset rotation to 0° |
| stop | () => void | Interrupt animation, decelerate to stop |
| getCurrentRotation | () => number | Current rotation in degrees |
| replaceData | (data: WheelItem[]) => void | Swap data without losing animation state |
Custom Renderers
Custom pointer
<Wheel
data={data}
renderPointer={() => (
<View style={styles.myArrow} />
)}
/>Custom segment label
<Wheel
data={data}
renderLabel={(item, position) => (
<Text style={{ color: '#fff', fontWeight: 'bold' }}>
{item.label}
</Text>
)}
/>Skia renderer
<Wheel data={data} renderer="skia" />Performance Notes
- All rotation math runs on the UI thread via Reanimated worklets. The JS thread is never blocked during a spin.
segmentLayoutsare memoised — they are only recalculated whendataorsizechanges.- Images on segments are cached by URI to avoid repeated network requests.
- Use
React.memoon any component you pass viarenderLabelorrenderSliceto avoid unnecessary re-renders.
Documentation
| Document | Description | |----------|-------------| | API.md | Full prop & method reference | | ARCHITECTURE.md | How the library is structured internally | | MIGRATION.md | Migrating from other wheel libraries | | CONTRIBUTING.md | Local dev setup and contribution guide |
Contributing
See the contributing guide to learn how to contribute to the repository and the development workflow.
Sponsor
If this library saves you time, consider buying me a coffee ☕
License
MIT
Made with create-react-native-library
Keywords: react native wheel, react native spinner, wheel of fortune react native, @vapng/react-native-wheel, spinning wheel component, react native fortune wheel, reanimated wheel, react native prize wheel, react native random picker
