Skip to content

React Native ​

@hapticjs/react-native provides a native haptic adapter that bridges @hapticjs to React Native's native haptic APIs.

Installation ​

bash
npm install @hapticjs/core @hapticjs/react-native
bash
pnpm add @hapticjs/core @hapticjs/react-native

Setup ​

Create a HapticEngine with the React Native adapter:

typescript
import { HapticEngine } from '@hapticjs/core';
import { ReactNativeHapticAdapter } from '@hapticjs/react-native';

const adapter = new ReactNativeHapticAdapter();
const engine = HapticEngine.create({ adapter });

// Use the same API as everywhere else
engine.tap();
engine.success();
engine.play('~~..##..@@');

Usage with React Hooks ​

Combine with @hapticjs/react for hook-based access:

tsx
import { HapticProvider } from '@hapticjs/react';
import { ReactNativeHapticAdapter } from '@hapticjs/react-native';

function App() {
  return (
    <HapticProvider config={{ adapter: new ReactNativeHapticAdapter() }}>
      <HomeScreen />
    </HapticProvider>
  );
}
tsx
import { useHaptic } from '@hapticjs/react';
import { TouchableOpacity, Text } from 'react-native';

function SubmitButton() {
  const { trigger } = useHaptic('success');

  return (
    <TouchableOpacity onPress={trigger}>
      <Text>Submit</Text>
    </TouchableOpacity>
  );
}

Platform Differences ​

PlatformBackend
iOSUIImpactFeedbackGenerator, UINotificationFeedbackGenerator
AndroidVibrator API via React Native's Vibration module

The adapter automatically maps semantic effects to the best native API available on the platform.

Impact Styles on iOS ​

The impact() method maps directly to iOS UIImpactFeedbackGenerator styles:

typescript
engine.impact('light');    // UIImpactFeedbackStyle.light
engine.impact('medium');   // UIImpactFeedbackStyle.medium
engine.impact('heavy');    // UIImpactFeedbackStyle.heavy
engine.impact('rigid');    // UIImpactFeedbackStyle.rigid
engine.impact('soft');     // UIImpactFeedbackStyle.soft

Example: Full App ​

tsx
import React from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { HapticEngine } from '@hapticjs/core';
import { ReactNativeHapticAdapter } from '@hapticjs/react-native';

const engine = HapticEngine.create({
  adapter: new ReactNativeHapticAdapter(),
});

export default function App() {
  return (
    <View style={styles.container}>
      <TouchableOpacity
        style={styles.button}
        onPress={() => engine.tap()}
      >
        <Text>Tap</Text>
      </TouchableOpacity>

      <TouchableOpacity
        style={styles.button}
        onPress={() => engine.success()}
      >
        <Text>Success</Text>
      </TouchableOpacity>

      <TouchableOpacity
        style={styles.button}
        onPress={() => engine.play('~~..##..@@')}
      >
        <Text>Pattern</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  button: { padding: 16, margin: 8, backgroundColor: '#3b82f6', borderRadius: 8 },
});

Released under the MIT License.