Amazon Developer

as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
Ring
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート

手順4: コードを移行する

手順4: コードを移行する

4.1 PropTypesを削除する

React 19では、ReactパッケージからPropTypesが削除されています。PropTypesの使用箇所はすべて、TypeScriptインターフェイスに移行する必要があります。

PropTypesの使用箇所をすべて検索する方法

grep -rn "from 'prop-types'" src/
grep -rn "\.propTypes\s*=" src/

移行パターン

// ❌ 更新前(RN 0.83で問題が発生)
import PropTypes from 'prop-types';

function UserCard({ name, email, age, onPress }) {
  return (
    <TouchableOpacity onPress={onPress}>
      <View>
        <Text>{name}</Text>
        <Text>{email}</Text>
        {age && <Text>年齢:{age}</Text>}
      </View>
    </TouchableOpacity>
  );
}

UserCard.propTypes = {
  name: PropTypes.string.isRequired,
  email: PropTypes.string.isRequired,
  age: PropTypes.number,
  onPress: PropTypes.func,
};

// ✅ 更新後
interface UserCardProps {
  name: string;
  email: string;
  age?: number;
  onPress?: () => void;
}

function UserCard({ name, email, age, onPress }: UserCardProps) {
  return (
    <TouchableOpacity onPress={onPress}>
      <View>
        <Text>{name}</Text>
        <Text>{email}</Text>
        {age && <Text>年齢:{age}</Text>}
      </View>
    </TouchableOpacity>
  );
}

4.2 defaultPropsを置き換える

React 19では、関数コンポーネントでのdefaultPropsのサポートが削除されています。代わりにデフォルトパラメーター値を使用します。

defaultPropsの使用箇所をすべて検索する方法

grep -rn "\.defaultProps\s*=" src/

移行パターン

// ❌ 更新前
MyComponent.defaultProps = {
  name: 'Default',
  age: 0,
  onPress: () => {},
};

// ✅ 更新後 - デフォルトパラメーターを使用
function MyComponent({ 
  name = 'Default', 
  age = 0, 
  onPress = () => {} 
}: MyComponentProps) {
  return <Text>{name}</Text>;
}

4.3 BackHandler.removeEventListenerを置き換える

BackHandler.removeEventListener()はReact Nativeによって削除されました。代わりにサブスクリプションパターンを使用します。

使用箇所をすべて検索する方法

grep -rn "BackHandler.removeEventListener" src/

移行パターン

// ❌ 更新前(RN 0.83でクラッシュ)
BackHandler.addEventListener('hardwareBackPress', handler);
// ...その後
BackHandler.removeEventListener('hardwareBackPress', handler);

// ✅ 更新後 - サブスクリプションパターン
const subscription = BackHandler.addEventListener('hardwareBackPress', handler);
// ...その後
subscription.remove();

useEffectを使用するReactコンポーネント内

useEffect(() => {
  const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
    // 戻るボタンが押下されたときの処理
    return true; // デフォルトの動作を抑制
  });

  return () => subscription.remove();
}, []);

4.4 useNativeDriverの混在使用を修正する

RN 0.72では、ネイティブドライバーとJSドライバーのアニメーションの混在はサポートされていませんでしたが、警告が生成されるだけでした。RN 0.83では、この混在により致命的なクラッシュ(SIGABRT)が発生します。

次の2つのルールがあり、両方とも適用されます。

  1. 値単位: 1つのAnimated.Valueは、その存続期間を通じてすべてのアニメーションで同じドライバーを使用する必要があります。
  2. ビュー単位(新しく適用): 1つのAnimated.View上の同じスタイルオブジェクトに結合されたすべてのAnimated.Valueインスタンスは、同じドライバーを使用する必要があります。

プロジェクトを検査する方法

grep -rn "useNativeDriver" src/

これが3つ以上出現するファイルには、ドライバーの混在するビューが含まれている可能性があります。

クラッシュパターンの例

// ❌ クラッシュ - scaleAnim(ネイティブ)とbackgroundAnim(JS)を同じビューで使用
<Animated.View style={{
  transform: [{ scale: scaleAnim }],             // useNativeDriver: true
  backgroundColor: backgroundAnim.interpolate()  // useNativeDriver: false
}}>
  {/* コンテンツ */}
</Animated.View>

// ✅ 修正後 - ドライバータイプで分けて入れ子のビューに分離
<Animated.View style={{ transform: [{ scale: scaleAnim }], opacity: opacityAnim }}>
  {/* ネイティブ駆動:transform、opacity */}
  <Animated.View style={{ backgroundColor: colorAnim.interpolate(...) }}>
    {/* JS駆動:backgroundColor */}
    {/* コンテンツ */}
  </Animated.View>
</Animated.View>

ドライバーの使用ルール

  • ネイティブドライバー(useNativeDriver: true):transformopacity。すべてのuseNativeDriver: trueを一律にfalseに変更しないでください。競合のある値だけを修正してください。
  • JSドライバー(useNativeDriver: false):backgroundColorwidthheight、色の補間。

4.5 従来のコンテキストAPIの使用箇所を更新する

React 19では、従来のコンテキストAPI(childContextTypesgetChildContext)が完全に削除されています。最新のコンテキストAPIを使用してください。

// ❌ 更新前 - 従来のコンテキスト(削除済み)
class Parent extends React.Component {
  getChildContext() {
    return { theme: 'dark' };
  }
  static childContextTypes = { theme: PropTypes.string };
}

// ✅ 更新後 - 最新のコンテキストAPI
const ThemeContext = React.createContext('light');

function Parent({ children }) {
  return (
    <ThemeContext.Provider value="dark">
      {children}
    </ThemeContext.Provider>
  );
}

function Child() {
  const theme = useContext(ThemeContext);
  return <Text>{theme}</Text>;
}

4.6 Reactフックの明示的なインポートを追加する

フックを使用するファイルでは、フックを明示的にインポートしないと、「ReferenceError: useState is not defined」というエラーが発生します。

// ✅ フックを常に明示的にインポート
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';

潜在的な問題を検出する方法

grep -rn "useState\|useEffect\|useCallback\|useMemo\|useRef" src/ | grep -v "import"

4.7 互換性のないツールを削除する

一部の開発ツールはReact 19と互換性がありません。

# @welldone-software/why-did-you-render(ピアreact@^18を宣言)を削除します。
npm uninstall @welldone-software/why-did-you-render

ほかにreact@^18をピア依存関係として固定する開発依存関係がないかどうかを確認します。

npm ls react 2>&1 | grep "peer"

4.8 SafeAreaViewの使用方法を更新する

React Native 0.83では、react-native-safe-area-contextが依存関係として必要です。アプリのルートコンポーネントを更新します。

// ✅ 更新後 - アプリをSafeAreaProviderでラップ
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';

function App() {
  return (
    <SafeAreaProvider>
      <AppContent />
    </SafeAreaProvider>
  );
}

function AppContent() {
  const insets = useSafeAreaInsets();
  
  return (
    <View style={{ 
      flex: 1,
      paddingTop: insets.top,
      paddingBottom: insets.bottom,
    }}>
      {/* アプリのコンテンツ */}
    </View>
  );
}

4.9 レイアウト値を密度非依存ピクセル(DIP)に変換する

Vega上のReact Native 0.83では、すべてのレイアウト値に密度非依存ピクセル(dp)が使用されます。キャンバスの基準サイズは960x540dpで、1080pディスプレイでのスケール係数は2になります。dp値は、フレームワークによって自動的に物理ピクセルにスケーリングされます。

ハードコードされているすべてのピクセル値を、スケール係数(1080pデバイスの場合は2)で除算します。

// ❌ 更新前(RN 0.72)- 物理ピクセル値
const styles = StyleSheet.create({
  container: {
    width: 1920,
    height: 1080,
    padding: 32,
  },
  title: {
    fontSize: 48,
    marginBottom: 24,
  },
});

// ✅ 更新後(RN 0.83)- dp値(2で除算した値)
const styles = StyleSheet.create({
  container: {
    width: 960,
    height: 540,
    padding: 16,
  },
  title: {
    fontSize: 24,
    marginBottom: 12,
  },
});

Last updated: 2026年8月4日