【ReactNative開発】Error: useTheme: theme is undefined. Seems you forgot to wrap your app in エラーが発生する

こんにちは、今週末もReactNative開発のトラブルシューティングメモです。今回は、Native Baseライブラリをアップデートしたことでハマりました・・・。

Contents

前提

  • React Native + Type Script + Expoでの開発

問題

NativeBaseライブラリのバージョンを2.x系から3.x系にあげると、以下のエラーがでてアプリが起動しなくなってしまった。

Error: useTheme: `theme` is undefined. Seems you forgot to wrap your app in `<NativeBaseProvider />`

This error is located at:
    in ForwardRef(Container)
    in ForwardRef(Container) (at signin.screen.tsx:18)
    in SignInScreen (created by inject-with-stores(SignInScreen))
    in inject-with-stores(SignInScreen) (at SceneView.tsx:122)
    in StaticContainer
    in StaticContainer (at SceneView.tsx:115)
    in EnsureSingleNavigator (at SceneView.tsx:114)
    in SceneView (at useDescriptors.tsx:153)
    in RCTView (at View.js:34)
    in View (at CardContainer.tsx:245)
    in RCTView (at View.js:34)
    in View (at CardContainer.tsx:244)
    in RCTView (at View.js:34)
    in View (at CardSheet.tsx:33)
    in ForwardRef(CardSheet) (at Card.tsx:573)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:555)
    in PanGestureHandler (at GestureHandlerNative.tsx:13)
    in PanGestureHandler (at Card.tsx:549)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:544)
    in RCTView (at View.js:34)
    in View (at Card.tsx:538)
    in Card (at CardContainer.tsx:206)
    in CardContainer (at CardStack.tsx:623)
    in RNSScreen (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at src/index.native.tsx:147)
    in Screen (at Screens.tsx:74)
    in MaybeScreen (at CardStack.tsx:616)
    in RNSScreenContainer (at src/index.native.tsx:186)
    in ScreenContainer (at Screens.tsx:50)
    in MaybeScreenContainer (at CardStack.tsx:498)
    in CardStack (at StackView.tsx:462)
    in KeyboardManager (at StackView.tsx:458)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at SafeAreaProviderCompat.tsx:42)
    in SafeAreaProviderCompat (at StackView.tsx:455)
    in GestureHandlerRootView (at GestureHandlerRootView.android.tsx:26)
    in GestureHandlerRootView (at StackView.tsx:454)
    in StackView (at createStackNavigator.tsx:87)
    in StackNavigator (at app.navigator.tsx:144)
    in AuthFlow (at app.navigator.tsx:304)
    in EnsureSingleNavigator (at BaseNavigationContainer.tsx:409)
    in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:91)
    in ThemeProvider (at NavigationContainer.tsx:90)
    in ForwardRef(NavigationContainer) (at app.navigator.tsx:302)
    in AppNavigator (created by inject-with-stores(AppNavigator))
    in inject-with-stores(AppNavigator) (at App.tsx:38)
    in MobXProvider (at App.tsx:37)
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:171:19 in handleException
at node_modules/react-native/Libraries/Core/ReactFiberErrorDialog.js:43:2 in showErrorDialog
at [native code]:null in commitRootImpl
at [native code]:null in performSyncWorkOnRoot
at [native code]:null in dispatchAction
at node_modules/@react-navigation/core/src/useSyncState.tsx:39:22 in React.useCallback$argument_0
at node_modules/@react-navigation/core/src/useOnAction.tsx:105:20 in React.useCallback$argument_0
at node_modules/@react-navigation/core/src/useNavigationHelpers.tsx:45:30 in dispatch
at node_modules/@react-navigation/core/src/useNavigationCache.tsx:79:10 in dispatch
at node_modules/@react-navigation/core/src/useNavigationCache.tsx:89:50 in acc.name
at app/screens/splash.screen.tsx:14:12 in setTimeout$argument_0
at [native code]:null in callFunctionReturnFlushedQueue


## その前にこんなワーニングも
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check your code at signin.screen.tsx:20.
    in SignInScreen (created by inject-with-stores(SignInScreen))
    in inject-with-stores(SignInScreen) (at SceneView.tsx:122)
    in StaticContainer
    in StaticContainer (at SceneView.tsx:115)
    in EnsureSingleNavigator (at SceneView.tsx:114)
    in SceneView (at useDescriptors.tsx:153)
    in RCTView (at View.js:34)
    in View (at CardContainer.tsx:245)
    in RCTView (at View.js:34)
    in View (at CardContainer.tsx:244)
    in RCTView (at View.js:34)
    in View (at CardSheet.tsx:33)
    in ForwardRef(CardSheet) (at Card.tsx:573)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:555)
    in PanGestureHandler (at GestureHandlerNative.tsx:13)
    in PanGestureHandler (at Card.tsx:549)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at Card.tsx:544)
    in RCTView (at View.js:34)
    in View (at Card.tsx:538)
    in Card (at CardContainer.tsx:206)
    in CardContainer (at CardStack.tsx:623)
    in RNSScreen (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at src/index.native.tsx:147)
    in Screen (at Screens.tsx:74)
    in MaybeScreen (at CardStack.tsx:616)
    in RNSScreenContainer (at src/index.native.tsx:186)
    in ScreenContainer (at Screens.tsx:50)
    in MaybeScreenContainer (at CardStack.tsx:498)
    in CardStack (at StackView.tsx:462)
    in KeyboardManager (at StackView.tsx:458)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at SafeAreaProviderCompat.tsx:42)
    in SafeAreaProviderCompat (at StackView.tsx:455)
    in GestureHandlerRootView (at GestureHandlerRootView.android.tsx:26)
    in GestureHandlerRootView (at StackView.tsx:454)
    in StackView (at createStackNavigator.tsx:87)
    in StackNavigator (at app.navigator.tsx:144)
    in AuthFlow (at app.navigator.tsx:304)
    in EnsureSingleNavigator (at BaseNavigationContainer.tsx:409)
    in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:91)
    in ThemeProvider (at NavigationContainer.tsx:90)
    in ForwardRef(NavigationContainer) (at app.navigator.tsx:302)
    in AppNavigator (created by inject-with-stores(AppNavigator))
    in inject-with-stores(AppNavigator) (at App.tsx:38)
    in MobXProvider (at App.tsx:37)
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)
at node_modules/react/cjs/react.development.js:220:4 in printWarning
at node_modules/react/cjs/react.development.js:196:16 in error
at node_modules/react/cjs/react.development.js:2215:11 in createElementWithValidation
at app/screens/signin.screen.tsx:20:20 in SignInScreen#render
at [native code]:null in performSyncWorkOnRoot
at [native code]:null in dispatchAction
at node_modules/@react-navigation/core/src/useSyncState.tsx:39:22 in React.useCallback$argument_0
at node_modules/@react-navigation/core/src/useOnAction.tsx:105:20 in React.useCallback$argument_0
at node_modules/@react-navigation/core/src/useNavigationHelpers.tsx:45:30 in dispatch
at node_modules/@react-navigation/core/src/useNavigationCache.tsx:79:10 in dispatch
at node_modules/@react-navigation/core/src/useNavigationCache.tsx:89:50 in acc.name
at app/screens/splash.screen.tsx:14:12 in setTimeout$argument_0
at [native code]:null in callFunctionReturnFlushedQueue

原因と解決方法

このStack Overflowを見て、解決した。App.tsx (App.js)において、Native BaseのNativeBaseProviderでWrapしないといけないようだ。

react native – Error: useTheme: `theme` is undefined. Seems you forgot to wrap your app in `<NativeBaseProvider />` – Stack Overflow

Before

  render(){
      return(
          <Provider stores={stores}>
            <AppNavigator/>
          </Provider>
      )
   }

After

#追加
import { NativeBaseProvider } from 'native-base';

...
  render(){
      return(
        <NativeBaseProvider>
          <Provider stores={stores}>
            <AppNavigator/>
          </Provider>
        </NativeBaseProvider>
      )
   }

NativeBaseProviderってなんだろう、これまで使わなくても動いていたのに・・・調べてみると公式Docにはこんな説明が。アプリで”テーマ”というものを使うために必要ならしい。はて、明示的にテーマを使った記憶はないのですが、3.xへのアップデートの中で、何かお作法が変わったのかもしれません・・(情報見つけられず・・)

この謎については、理解が深まったらまた更新しようと思います。

Setup NativeBase Provider | NativeBase

NativeBaseProvider is a component that makes the theme available throughout your app. It uses React’s Context API. Add NativeBaseProvider to the root of your app and update App.js as follows:

おしまい

[番外編] ReactNativeをもっと学ぶなら・・・

React Nativeをもっとちゃんと学びたい!という方は、こちらにおすすめコンテンツをまとめましたので、ご参考にしていただければと思います・・!

土台のJavaScript/TypeScriptに不安がある方は、こちらもまとめましたので、ご参考になりましたら幸いです。

この記事を気に入っていただけたらシェアをお願いします!
ABOUT US
Yuu113
初めまして。ゆうたろうと申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。 日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。