react-native-unistyles-v3 について
react-native-unistyles-v3は、Unistyles v3でテーマ対応やレスポンシブな画面を構築するReact Native開発者向けのスタイリングスキルです。C++コアとビルド時処理により、再レンダリングを伴わないスタイル更新を扱います。
主な機能
- 01静的スタイルとテーマ連動スタイル
- 02テーマとブレークポイントの設定
- 03プロパティに基づくスタイルバリアント
- 04テーマ値のコンポーネントプロパティへの割り当て
- 05Babel、Metro、Re.Packとの統合
活用シーン
- 01アプリへのライト・ダークテーマ追加
- 02画面サイズに応じたレイアウト調整
- 03コンポーネントのサイズバリアント作成
- 04テーマカラーのサードパーティ製コンポーネントへの適用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jpudysz/ react-native-unistyles --skill react-native-unistyles-v3インストール後、Claude Code で/react-native-unistyles-v3を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-reference.mdcommon-issues.mdsetup-guide.mdstyling-patterns.mdthird-party-integration.md詳細
React Native Unistyles v3 スキル
React Native Unistyles v3 のスタイリングを支援します。v3 は、C++ コア(Nitro Modules)と、ビルド時に StyleSheet を処理する Babel プラグインを備えた、再レンダリングを発生させないスタイリングライブラリです(3.6.0 以降、Metro アプリでは実験的なゼロコンフィグの Metro 統合も利用できます)。React Native の StyleSheet を、リアクティブでテーマ対応かつレスポンシブなシステムに置き換えます。
前提条件
- React Native 0.81 以降で、新しいアーキテクチャが必須(RN 0.76 以降はデフォルトで有効、RN 0.82 以降は唯一のアーキテクチャ)
- React 19 以降(実行時に強制されます)
react-native-nitro-modules(ネイティブブリッジの依存関係。正確なバージョンを固定してください — Unistyles 3.4.0 以降では>= 0.37.1が必要です)- iOS 15.1 以降、Android 7 以降
react-native-edge-to-edgeは不要です(v3.1.0 以降は任意で、現在は非推奨です)。代わりにandroid/gradle.propertiesでedgeToEdgeEnabled=trueを設定してください(Expo SDK 54 以降では自動的に有効になります)- Expo SDK 54 以降(Expo を使用する場合。Expo Go とは互換性がありません — 開発クライアントまたは prebuild が必要です)
- Xcode 16.4 以降(iOS 用。Nitro Modules が必要とします)
ワークフロー
- まずユーザーのコードを読む — 現在のセットアップ、インポート、スタイリング方法を把握します
- 意図を特定する — 新規セットアップ、テーマの追加、レスポンシブデザイン、問題の修正など
- v3 のパターンを適用する — このスキルの適切な API を使用し、詳細についてはリファレンスファイルを参照します
- 正確性を確認する — 重要なルール違反(スプレッド、バレル再エクスポートなど)がないか確認します
クイックリファレンス
StyleSheet.create — 3 つのオーバーロード
import { StyleSheet } from 'react-native-unistyles'
// 1. Static object compatible with React Native StyleSheet.create
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 }
})
// 2. Theme function (reactive to theme changes, zero re-renders)
const styles = StyleSheet.create(theme => ({
container: { backgroundColor: theme.colors.background }
}))
// 3. Theme + miniRuntime function (reactive to theme AND device state)
const styles = StyleSheet.create((theme, rt) => ({
container: {
backgroundColor: theme.colors.background,
paddingTop: rt.insets.top,
width: rt.screen.width > 768 ? 500 : rt.screen.width - 32
}
}))
StyleSheet.configure — 一度だけ行うセットアップ
StyleSheet.configure({
themes: { light: lightTheme, dark: darkTheme },
breakpoints: { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200 },
settings: {
initialTheme: 'light', // or: () => storage.getString('theme') ?? 'light'
// adaptiveThemes: true, // auto-switch light/dark based on OS (mutually exclusive with initialTheme)
// CSSVars: true, // web: themes as CSS variables (default: true)
// nativeBreakpointsMode: 'pixels' | 'points' // default 'pixels' = compare against rt.screen (pt/dp)
}
})
バリアント
const styles = StyleSheet.create(theme => ({
button: {
variants: {
size: {
small: { padding: 4 },
medium: { padding: 8 },
large: { padding: 16 },
},
color: {
primary: { backgroundColor: theme.colors.primary },
secondary: { backgroundColor: theme.colors.secondary },
}
},
compoundVariants: [
{ size: 'large', color: 'primary', styles: { borderWidth: 2 } }
],
}
}))
// In component — call useVariants BEFORE accessing styles (always pass an object, `{}` for defaults)
styles.useVariants({ size: 'large', color: 'primary' })
return <View style={styles.button} />
withUnistyles — テーマ/ランタイムをスタイル以外のプロパティにマッピングするか、Unistyles がバインドできないビューをラップします
style のみを受け取る React Native/Reanimated のビューは、ラップする必要はありません。color/trackColor などのプロパティ、contentContainerStyle、またはネイティブ ref を公開しないサードパーティ製ビューには withUnistyles を使用します。
import { withUnistyles } from 'react-native-unistyles'
import { Button } from 'some-library'
const UniButton = withUnistyles(Button, (theme, rt) => ({
color: theme.colors.primary,
size: rt.screen.width > 400 ? 'large' : 'small'
}))
// Usage: <UniButton title="Press me" />
// Per-instance mapping: <UniButton uniProps={theme => ({ color: isOn ? theme.colors.on : theme.colors.off })} />
重要なルール
-
スタイルを絶対に展開しないでください —
{...styles.x}は C++ のプロキシバインディングを壊します。必ず配列構文を使ってください:[styles.x, styles.y]または[styles.x, { marginTop: 10 }] -
バレルファイルから StyleSheet を再エクスポートしないでください —
react-native-unistylesから直接インポートしてください。rootの外では、Babel プラグインがStyleSheet.createを認識するのは、そのインポート経由(またはautoProcessImports)のみです。そのため、再エクスポートすると検出が気づかれないまま機能しなくなります。(Metro インテグレーションは独自モジュールからの再エクスポートも検出しますが、直接インポートはどこでも機能します。) -
ビルド時のインテグレーションが必須です — 次のいずれかを使用してください。
- Babel プラグイン(デフォルト):babel.config.js に
['react-native-unistyles/plugin', { root: 'src' }]を指定します(rootは必須で、その配下のすべてのファイルが処理されます) - Metro インテグレーション(3.6.0 以降、実験的、Metro のみ):metro.config.js で
react-native-unistyles/metroのwithUnistylesConfig(config)をオプションなしで使用し、Babel プラグインを削除してください(両方を設定するとエラーになります)。babel.config.jsのpluginsにbabel-plugin-react-compilerを記載しているベア RN アプリでは、Babel プラグインを残してください。これらのプラグインは Metro のプラグインより先に実行されるため、React Compiler が先にuseVariantsを認識してしまいます - Re.Pack:
react-native-unistyles/repack-pluginのRepackUnistylePlugin
いずれも設定しないと、スタイルはリアクティブになりません。
- Babel プラグイン(デフォルト):babel.config.js に
-
StyleSheet は
react-native-unistylesからのみインポートしてください — RN の StyleSheet API(hairlineWidth、compose、flatten、absoluteFill)をすべてポリフィルします。すべてのimport { StyleSheet } from 'react-native'を置き換えてください。 -
バリアントに依存するスタイルにアクセスする前に、
styles.useVariants()を呼び出してください — React フックと同様に扱ってください(コンポーネントの先頭で呼び出します)。必ずオブジェクトを渡してください。useVariants(undefined)はネイティブでエラーになるため、defaultバリアントを選択するには{}を使用してください。 -
useUnistyles()よりStyleSheet.create(theme => ...)を優先してください — テーマ関数による再レンダリングは発生しません。一方、useUnistyles()は、読み取ったtheme/rtの値が変わるたびに再レンダリングされます(そこでrt.insets.imeを読み取らないでください。キーボードのフレームごとに再レンダリングされます)。 -
StyleSheet.create()を呼び出す前に、StyleSheet.configure()を呼び出す必要があります — 通常は、コンポーネントがレンダリングされる前にアプリのエントリーポイントで呼び出します。 -
動的関数の引数はシリアライズ可能でなければなりません — Unistyles は引数を C++ に保存し、テーマやランタイムの変更時に関数を再実行します。関数は削除され、
Date/Map/Set/クラスインスタンスはプレーンオブジェクトになります。プリミティブ値またはプレーンオブジェクトを渡してください(例:date.getTime())。
判断ツリー
スタイリング方法の選択
Need theme/runtime in styles?
├─ YES → StyleSheet.create((theme, rt) => ...) [zero re-renders]
└─ NO → StyleSheet.create({ ... }) [static styles]
Need theme values as non-style props?
├─ YES → withUnistyles(Component, (theme, rt) => ({ propName: theme.value }))
└─ NO → Pass Unistyles styles via style prop directly
Need theme/runtime in component logic (not just styles)?
├─ YES → useUnistyles() hook [re-renders when read values change]
└─ NO → Use StyleSheet.create with theme function
サードパーティコンポーネントとの連携
Passing a Unistyles style to `contentContainerStyle` (ScrollView/FlatList)?
├─ YES → withUnistyles(ScrollView) — auto-maps style + contentContainerStyle
└─ NO → react-native / react-native-reanimated view with a `style` prop?
├─ YES → Pass Unistyles styles directly (Babel swaps in ref-borrowing factories)
└─ NO → Third-party view built on RN components (in node_modules)?
├─ YES → Metro integration: works as-is (node_modules are covered)
│ Babel plugin: add its path to autoProcessPaths (e.g. 'some-lib/src/components')
└─ Still not updating / needs theme-derived props (color, size, ...)?
├─ YES → withUnistyles(Component, (theme, rt) => ({ prop: theme.value }))
└─ Last resort → useUnistyles() (re-renders the component)
Your own files outside `root` (monorepo package) not updating?
→ autoProcessImports: ['@my-org/styles'] (force-processes any file importing it; not needed with the Metro integration)
リファレンスファイル
- セットアップ、インストール、Babel プラグイン、Metro インテグレーション、Re.Pack、TypeScript、テスト、Expo Router:references/setup-guide.md を参照してください
- すべてのエクスポートの完全な API:references/api-reference.md を参照してください
- コードパターン:テーマ、バリアント、ブレークポイント、Web、SSR、Reanimated:references/styling-patterns.md を参照してください
- withUnistyles、autoProcessPaths/Imports、React Compiler、Reanimated、エッジツーエッジ、フリーズされた画面、FlatList:references/third-party-integration.md を参照してください
- 150 件以上の GitHub の課題とその解決策に基づくトラブルシューティング:references/common-issues.md を参照してください