You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Expo项目闪屏不显示(仅白屏)问题求助

Expo托管React Native项目闪屏不显示问题排查与解决

我运行着一个Expo托管式React Native项目,初始化时闪屏正常显示,但现在完全无法看到闪屏,仅显示空白白屏(无报错)。闪屏加载后的所有功能均正常,急需解决闪屏显示问题。

已尝试的操作

  • 在iOS模拟器、iOS真机、Android模拟器上运行,问题一致
  • 删除node_modules和package-lock.json后执行npm i
  • 清除Expo和npm的缓存
  • 将app.js返回内容替换为仅<View><Text>...</Text></View>,问题仍存在

项目配置

package.json

{
  "name": "placeholder",
  "version": "1.0.0",
  "description": "placeholder",
  "main": "node_modules/expo/AppEntry.js",
  "type": "commonjs",
  "private": true,
  "scripts": {
    "type:check": "npx tsc",
    "format:check": "prettier --check \"src/**/*\"",
    "format:write": "prettier --write \"src/**/*\"",
    "lint:check": "eslint \"App.tsx\" \"src/**/*\"",
    "lint:fix": "eslint --fix \"App.tsx\" \"src/**/*\"",
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "engines": {
    "node": "16.x"
  },
  "dependencies": {
    "@react-native-async-storage/async-storage": "~1.17.3",
    "@react-navigation/drawer": "^6.4.3",
    "@react-navigation/native": "^6.0.11",
    "@react-navigation/native-stack": "^6.7.0",
    "@react-navigation/stack": "^6.2.2",
    "@reduxjs/toolkit": "^1.8.4",
    "dotenv": "^16.0.1",
    "expo": "~46.0.6",
    "expo-status-bar": "~1.4.0",
    "react": "18.0.0",
    "react-dom": "18.0.0",
    "react-native": "0.69.4",
    "react-native-gesture-handler": "~2.5.0",
    "react-native-reanimated": "~2.9.1",
    "react-native-screens": "~3.15.0",
    "react-native-web": "~0.18.7",
    "react-redux": "^8.0.2",
    "styled-components": "^5.3.5",
    "expo-screen-orientation": "~4.3.0",
    "expo-splash-screen": "~0.16.1",
    "react-native-safe-area-context": "4.3.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@redux-devtools/core": "^3.13.1",
    "@types/react": "~18.0.14",
    "@types/react-native": "~0.69.1",
    "@types/react-redux": "^7.1.24",
    "@types/styled-components": "^5.1.26",
    "@types/styled-components-react-native": "^5.1.3",
    "@typescript-eslint/eslint-plugin": "^5.33.1",
    "eslint": "^8.22.0",
    "eslint-config-standard-with-typescript": "^22.0.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-n": "^15.2.4",
    "eslint-plugin-promise": "^6.0.0",
    "eslint-plugin-react": "^7.30.1",
    "eslint-plugin-react-hooks": "^4.6.0",
    "prettier": "^2.7.1",
    "typescript": "^4.7.4"
  }
}

app.json

{
  "expo": {
    "name": "placeholder",
    "slug": "placeholder",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "userInterfaceStyle": "light",
    "splash": {
      "image": "./assets/images/splash.png",
      "resizeMode": "cover",
      "backgroundColor": "#1D1A1F"
    },
    "updates": {
      "fallbackToCacheTimeout": 0
    },
    "assetBundlePatterns": ["**/*"],
    "ios": {
      "supportsTablet": true,
      "requireFullScreen": true
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#1D1A1F"
      }
    },
    "web": {
      "favicon": "./assets/images/favicon.png"
    }
  }
}

babel.config.js

module.exports = function (api) {
  api.cache(true)
  return {
    presets: ['babel-preset-expo'],
    plugins: ['react-native-reanimated/plugin']
  }
}

app.tsx

import 'react-native-gesture-handler'
import Constants from 'expo-constants'
import { useState, useEffect } from 'react'
import { useFonts } from 'expo-font'
import * as SplashScreen from 'expo-splash-screen'
import * as ScreenOrientation from 'expo-screen-orientation'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { Provider } from 'react-redux'
import { ThemeProvider } from 'styled-components/native'
import store from './src/redux/store'
import { lightTheme, darkTheme } from './src/res/theme/theme'
import Loading from './src/screens/loading/loading'
import { logger } from './src/logger/logger'
import Application from './src/components/application/application'

// Function to keep the splash screen visible while we fetch resources
SplashScreen.preventAutoHideAsync()
  .then((data) => logger.log(`SplashScreen.preventAutoHideAsync() succeeded: ${data.toString()}`))
  .catch(logger.warn)

logger.log('NODE_ENV: ', Constants?.manifest?.extra?.env) //eslint-disable-line

export const App = (): JSX.Element => {
  const [fontsLoaded] = useFonts({
    SedgwickAveDisplay: require('./assets/fonts/sedgwick-ave-display/SedgwickAveDisplay-Regular.ttf'),
    QuicksandRegular: require('./assets/fonts/Quicksand/static/Quicksand-Regular.ttf'),
    QuicksandSemiBold: require('./assets/fonts/Quicksand/static/Quicksand-SemiBold.ttf'),
    QuicksandBold: require('./assets/fonts/Quicksand/static/Quicksand-Bold.ttf')
  })
  const [loading, setLoading] = useState(true)
  const [theme, setTheme] = useState('light')
  const selectedTheme = theme === 'dark' ? darkTheme : lightTheme

  // Load the app here
  useEffect(() => {
    // Hide splash screen after 2 seconds
    setTimeout(() => {
      SplashScreen.hideAsync()
        .then((data) => logger.log(`SplashScreen.hideAsync() succeeded: ${data.toString()}`))
        .catch(logger.warn)
    }, 2000)

    ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP)
      .then(() => {
        logger.log('ScreenOrientation.lockAsync() succeeded')

        return AsyncStorage.getItem('@theme')
      })
      .then((data) => {
        if (data) setTheme(data)

        setLoading(false)
      })
      .catch((e) => {
        logger.warn(e)
        setLoading(false)
      })
  }, [])

  if (loading || !fontsLoaded) {
    return <Loading />
  }

  return (
    <SafeAreaProvider>
      <Provider store={store}>
        <ThemeProvider theme={selectedTheme}>
          <Application />
        </ThemeProvider>
      </Provider>
    </SafeAreaProvider>
  )
}

export default App

排查与修复方案

1. 调整SplashScreen.preventAutoHideAsync执行时机

你在组件外部调用SplashScreen.preventAutoHideAsync(),可能导致竞态问题——Expo闪屏可能已自动隐藏,此调用才生效。将逻辑移至组件内部useEffect,确保挂载后立即执行:

export const App = (): JSX.Element => {
  const [fontsLoaded] = useFonts({
    // 字体配置保留
  })
  const [loading, setLoading] = useState(true)
  const [theme, setTheme] = useState('light')
  const selectedTheme = theme === 'dark' ? darkTheme : lightTheme

  useEffect(() => {
    const prepareApp = async () => {
      try {
        await SplashScreen.preventAutoHideAsync()
        logger.log('SplashScreen.preventAutoHideAsync() succeeded')
      } catch (e) {
        logger.warn(e)
      }

      try {
        await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP)
        logger.log('ScreenOrientation.lockAsync() succeeded')
        
        const savedTheme = await AsyncStorage.getItem('@theme')
        if (savedTheme) setTheme(savedTheme)
      } catch (e) {
        logger.warn(e)
      } finally {
        // 等待字体加载完成后再处理闪屏隐藏
        const waitForFonts = new Promise(resolve => {
          const interval = setInterval(() => {
            if (fontsLoaded) {
              clearInterval(interval)
              resolve(true)
            }
          }, 50)
        })
        
        await waitForFonts
        setTimeout(() => {
          SplashScreen.hideAsync()
            .then(data => logger.log(`SplashScreen.hideAsync() succeeded: ${data.toString()}`))
            .catch(logger.warn)
          setLoading(false)
        }, 2000)
      }
    }

    prepareApp()
  }, [fontsLoaded])

  // 其余代码保留
}

2. 检查闪屏资源有效性

  • 确认./assets/images/splash.png文件存在,尺寸符合Expo要求(建议:iOS 2208×2208,Android 1280×1920)
  • 可尝试在assetBundlePatterns中明确指定闪屏路径:["assets/images/*"],确保资源被正确打包

3. 排查Loading组件干扰

你在加载状态返回的<Loading />可能是白底,覆盖了Expo闪屏。暂时注释该返回,测试闪屏是否显示:

// if (loading || !fontsLoaded) {
//   return <Loading />
// }
if (!fontsLoaded) {
  return null // 让Expo闪屏正常显示
}

若闪屏恢复,说明Loading组件需调整样式(比如设置透明背景)。

4. 修复版本兼容性问题

Expo 46对应的expo-splash-screen@~0.16.1存在自动隐藏bug,可尝试:

  • 升级至Expo 47+
  • 降级expo-splash-screen到兼容版本:
npm install expo-splash-screen@0.15.1

5. 彻底清理缓存

执行以下命令重置项目缓存:

expo start -c
npm cache clean --force
rm -rf node_modules package-lock.json
npm install

内容的提问来源于stack exchange,提问作者mprouve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 06:54:25