React Native Expo中Font.loadAsync未完成组件已用字体问题
解决Expo预加载字体后仍提示「You need to wait for Font.loadAsync to complete before using the font」的问题
你的代码存在逻辑错误,导致自定义字体未被正确预加载:
cacheFonts函数的作用是接收字体配置对象,为每个配置调用Font.loadAsync生成加载Promise。但你在传参时,对自定义字体提前调用了Font.loadAsync(...),把返回的Promise传给了cacheFonts,导致cacheFonts内部会对这个Promise再次调用Font.loadAsync,完全偏离预期逻辑。自定义字体实际未加载完成,Promise.all就已执行完毕并设置mainScreenIsReady,最终组件渲染时字体还没加载好,触发报错。
修正步骤
- 直接传入字体配置对象到
cacheFonts,不要提前调用Font.loadAsync - 确保所有传入
cacheFonts的元素都是标准字体配置对象(比如Entypo.font就是符合要求的格式)
修正后的完整代码
import React, { useEffect, useState } from "react"; import { Text, View } from "react-native"; import * as Font from "expo-font"; import Entypo from "@expo/vector-icons/Entypo"; function cacheImages(images) { return images.map((image) => { if (typeof image === "string") { return Image.prefetch(image); } else { return Asset.fromModule(image).downloadAsync(); } }); } function cacheFonts(fonts) { return fonts.map((font) => Font.loadAsync(font)); } export default function MainScreen() { const [mainScreenIsReady, setMainScreenIsReady] = useState(false); useEffect(() => { async function loadResourcesAndDataAsync() { try { const imageAssets = cacheImages([]); // 修正:直接传入字体配置对象,而非提前调用Font.loadAsync const fontAssets = cacheFonts([ Entypo.font, { SFProBold: require("../assets/fonts/SF-Pro-Text-Bold.otf"), }, ]); await Promise.all([...imageAssets, ...fontAssets]); } catch (e) { console.warn(e); } finally { setMainScreenIsReady(true); } } loadResourcesAndDataAsync(); }, []); return ( <> {mainScreenIsReady && ( <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }} > <Text style={{ fontFamily: "SFProBold" }}>SplashScreen Demo! 👋</Text> <Entypo name="rocket" size={30} /> </View> )} </> ); }
修正后,cacheFonts会分别对Entypo.font和自定义字体配置调用Font.loadAsync,生成正确的加载Promise数组。Promise.all会等待所有字体加载完成后再设置mainScreenIsReady,此时组件渲染时字体已加载完毕,不会再出现报错。
内容的提问来源于stack exchange,提问作者ColstonBod-oy
相关产品推荐
相关产品推荐

