Error updating from Expo SDK 38 to 40.

Please provide the following:

  1. SDK Version: 30
  2. Platforms(Android/iOS/web/all): All

Hi all :slight_smile: !!

After upgrading from Expo SDK 38 to SDK 40, I was presented with the following errors.

I’m quite confused as to what the issue is with the errors as they weren’t present before the update. I checked the changelogs, and I wasn’t able to find any relevant information.

Has anyone experienced this issue? How do I debug this?

Any help is gladly appreciated. Thanks in advance!

see: https://stackoverflow.com/questions/34130539/uncaught-error-invariant-violation-element-type-is-invalid-expected-a-string

this means you are trying to render a component that is undefined, eg:

const MyComponent = undefined;

// later

return <MyComponent />

you’ll have to trace down where this came from

Hi Brent! Thanks for helping.

From the error message, it instructs me to check the render method of “App”.

I assume that this must be the App.js file? I’d included the code from my App.js for your reference.

I’m not quite sure what to look for exactly. Interestingly, I didn’t get this issue before upgrading to SDK 40. After reading through the Expo medium post for the SDK updates and the changelogs, I don’t recall seeing anything regarding semantic changes.

With that said, what do you think the issue may be with my code?

import {
  Platform,
  StatusBar,
  StyleSheet,
  View,
  ActivityIndicator,
  Dimensions,
  Linking,
} from "react-native";
import { NavigationActions } from "react-navigation";
import { AppLoading } from "expo-app-loading";
import { Asset } from "expo-asset";
import * as Font from "expo-font";
import React from "react";
import { Ionicons } from "@expo/vector-icons";
import AppNavigator from "./navigation/AppNavigator";
import MainTabNavigator from "./navigation/MainTabNavigator";
import { AsyncStorage } from "react-native";
import { Provider } from "react-redux";
import configureStore from "./redux/app-redux";
import { PersistGate } from "redux-persist/integration/react";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
import { Notifications } from "expo";
import NetInfo from "@react-native-community/netinfo";
import styled from "styled-components";
import FlashMessage from "react-native-flash-message";
import GroupJoinAnimation from "./components/animations/GroupJoinAnimation";
import ActivitySignUpAnimation from "./components/animations/ActivitySignUpAnimation";
import Header3Text from "./components/textStyles/Header3Text";
import OverlineText from "./components/textStyles/OverlineText";
import * as TaskManager from "expo-task-manager";
import * as Location from "expo-location";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      // State Variables
      isLoadingComplete: false,
      isAuthenticated: false, // Check is user is authenticated.
    };
  }


  renderLoading = () => {
    <View style={styles.container}>
      <ActivityIndicator size="large" />
    </View>;
  };

  render() {
    if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
      return (
        <AppLoading
          startAsync={this._loadResourcesAsync}
          onError={this._handleLoadingError}
          onFinish={this._handleFinishLoading}
        />
      );
    } else {
      return (
        //
        // If the user is authenticated then we send them to the MainTabNavigation,
        // otherwise, we send them to the AppNavigator with the Login and Signup flow.
        //
        <ActionSheetProvider>
          <Provider store={store}>
            <PersistGate persistor={persistor} loading={this.renderLoading()}>
              <View style={styles.container}>
                {Platform.OS === "ios" && <StatusBar barStyle="default" />}
                {Platform.OS === "android" && (
                  <View style={styles.statusBarUnderlay} />
                )}
                {this.state.isAuthenticated ? (
                  <Container>
                    <MainTabNavigator />
                  </Container>
                ) : (
                  <AppNavigator />
                )}
              </View>
            </PersistGate>
          </Provider>
        </ActionSheetProvider>
      );
    }
  }

  _loadResourcesAsync = async () => {
    return Promise.all([
      Asset.loadAsync([
        require("./assets/images/robot-dev.png"),
        require("./assets/images/robot-prod.png"),
      ]),
      Font.loadAsync({
        // This is the font that we are using for our tab bar
        ...Ionicons.font,
        // We include SpaceMono because we use it in HomeScreen.js. Feel free
        // to remove this if you are not using it in your app
        "space-mono": require("./assets/fonts/SpaceMono-Regular.ttf"),
        icomoon: require("./assets/fonts/SpaceMono-Regular.ttf"),
      }),
    ]);
  };

  _handleLoadingError = (error) => {
    // In this case, you might want to report the error to your error
    // reporting service, for example Sentry
    console.warn(error);
  };

  _handleFinishLoading = () => {
    this.setState({ isLoadingComplete: true });
  };
}

Thanks!

try changing your code to remove everything from App.js and just render a “hello world” react native example. does that work? if so, slowly add things back until you have the problem again. then you’ve found the source of it.

it’s not ideal but react isn’t great at the moment at helping narrow down the source of this specific error and it shouldn’t take more than a minute or two to do

1 Like

Hey Brent! This is a great approach. I was able to pinpoint the issue. It turns out that I did the following:

import { AppLoading } from "expo-app-loading";

instead of

import AppLoading from "expo-app-loading";

The former is the correct notation as of Expo SDK 40.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.