Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React native: TypeError: null is not an object (evaluating 'SplashScreen.preventAutoHide')

My react native app was working just fine before I used expo eject. I ejected it because I now intend to build and release the app to the ios app store. As soon as I attempt to start the ejected app using react-native run-ios after it's been ejected I get the exception below.

Please could someone help to understand what's causing this issue and how to tackle it?

react Native versions as follows:

react-native-cli: 2.0.1
react-native: 0.61.5

enter image description here

TypeError: null is not an object (evaluating 'SplashScreen.preventAutoHide')

This error is located at:
    in AppLoading (at AppLoading.js:52)
    in AppLoading (at App.js:464)
    in App (at renderApplication.js:40)
    in RCTView (at AppContainer.js:101)
    in RCTView (at AppContainer.js:119)
    in AppContainer (at renderApplication.js:39)

preventAutoHide
    SplashScreen.js:4:21
AppLoading#constructor
    AppLoadingNativeWrapper.js:6:8
renderRoot
    [native code]:0
runRootCallback
    [native code]:0
renderApplication
    renderApplication.js:52:52
runnables.appKey.run
    AppRegistry.js:116:10
runApplication
    AppRegistry.js:197:26
callFunctionReturnFlushedQueue
    [native code]:0
like image 713
user3391835 Avatar asked Apr 06 '20 19:04

user3391835


2 Answers

The AppLoading component is not available in the bare workflow. As @gaurav-roy said you have to refactor your code.

  1. Install the expo-splash-screen package with npm install expo-splash-screen

  2. Add a splash-screen to your Android and iOS projects. Run npm run expo-splash-screen --help and follow the instructions of this CLI tool. (Because of a bug you might have to run the command again with the -p "ios" flag if it only adds the SplashScreen for Android after running it.

  3. Change your code inside App.tsx in a similar way as in this example.

    If you're working with hooks you probably want to add an useEffect hook with an empty dependency list which runs an async function. Here an example of how it could be done:

const App = (props: Props) => {
  const [isLoadingComplete, setLoadingComplete] = useState(false);
  
  const init = async () => {
  try {
    // Keep on showing the SlashScreen
    await SplashScreen.preventAutoHideAsync();
    await loadResourcesAsync();
  } catch (e) {
    console.warn(e);
  } finally {
    setLoadingComplete(true);
    // Hiding the SplashScreen
    await SplashScreen.hideAsync();
  }
  
  useEffect(() => {
    init();
  }, []);

  const renderApp = () => {
    if (!isLoadingComplete && !props.skipLoadingScreen) {
      return null;
    }

    return (
      <Main />
    );
  };
  return <StoreProvider>{renderApp()}</StoreProvider>;
}
like image 105
Andru Avatar answered Nov 08 '22 23:11

Andru


As its evident from docs , SplashScreen is an inbuilt api for expo apps, and since you ejected it , it throws an error since it cant be used.

You can see this in the docs expo splashscreen .

First you should download npm i expo-splash-screen

And then change your import statement to :

import * as SplashScreen from 'expo-splash-screen';

Hope it helps. feel free for doubts

like image 6
Gaurav Roy Avatar answered Nov 08 '22 21:11

Gaurav Roy