Expo+NativeBase开发 函数组件用Hooks加载Roboto_medium字体报错求解
函数组件下加载NativeBase依赖字体的正确实现
你之前两种写法的失败原因
- 直接把
useEffect回调设为async函数的写法本质无效:useEffect本身同步执行,遇到async函数会立刻拿到一个未完成的Promise,根本不会等字体加载完成就触发首次渲染,此时NativeBase组件找不到已加载的Roboto_medium字体,自然会抛出报错。 - 在
useEffect里写立即执行异步函数的常见疏漏:很多人写完Font.loadAsync的逻辑就结束了,没有严格绑定「字体加载完成前不渲染正式页面」的逻辑,要么过早关闭占位加载页,要么状态更新时序错配,导致字体还在加载中页面就已经渲染了依赖字体的NativeBase组件。
核心判断逻辑:无论采用哪种代码写法,只要字体加载完成的Promise还没resolve,就绝对不能渲染依赖NativeBase字体的正式页面,否则必然触发字体未加载的报错。
标准实现步骤
- 引入对应依赖:
expo-font的字体加载接口、expo-app-loading的占位加载组件、NativeBase要求的全部字体资源。 - 用状态变量跟踪字体加载进度,初始状态设为“未加载完成”。
- 在
useEffect中执行一次性的字体加载逻辑:不要把useEffect的回调直接写成async,而是在回调内部定义独立的异步加载函数,等Font.loadAsync全部执行完成后,再把字体加载状态更新为“已完成”。注意:
useEffect的依赖数组设为空数组[]即可,保证字体加载逻辑仅在组件首次挂载时执行一次,避免重复加载触发异常。 - 做严格的状态分支判断:字体加载完成前统一返回AppLoading占位,不渲染任何包含NativeBase组件的正式内容;等状态更新为加载完成后,再渲染正式的应用页面。
可直接运行的参考代码
import React, { useState, useEffect } from 'react'; import { View } from 'react-native'; import { NativeBaseProvider, Text } from 'native-base'; import * as Font from 'expo-font'; import AppLoading from 'expo-app-loading'; // 导入NativeBase官方要求的字体资源,路径与项目内实际位置匹配即可 import Roboto from 'native-base/Fonts/Roboto.ttf'; import RobotoMedium from 'native-base/Fonts/Roboto_medium.ttf'; import Ionicons from '@expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/Ionicons.ttf'; export default function RootApp() { const [isFontReady, setIsFontReady] = useState(false); useEffect(() => { // 内部定义独立的异步加载函数,不直接给useEffect写async回调 const loadCustomFonts = async () => { await Font.loadAsync({ Roboto: Roboto, Roboto_medium: RobotoMedium, Ionicons: Ionicons, }); // 字体全部加载完成后更新状态 setIsFontReady(true); }; loadCustomFonts(); }, []); // 字体未加载完成时,仅展示占位组件,不渲染正式页面 if (!isFontReady) { return <AppLoading />; } // 字体加载完成后再渲染依赖NativeBase组件的页面 return ( <NativeBaseProvider> <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>字体加载完成,NativeBase组件可正常渲染</Text> </View> </NativeBaseProvider> ); }
容易遗漏的细节
- 不需要重复在多个子组件里写字体加载逻辑:把整套字体加载逻辑放在应用最根组件的位置,根组件完成字体加载后,所有下层子组件使用NativeBase的字体配置都会正常生效。
- 加载字体时不要漏写资源条目:必须把NativeBase运行需要的
Roboto、Roboto_medium、配套图标字体全部传入Font.loadAsync,少加载任意一个都会触发对应的字体缺失报错。 - 如果使用NativeBase v3及以上版本,也可以调用官方提供的
useFontsHooks简化书写,底层实现逻辑和上述手动管理状态的流程完全一致,不需要手动维护加载状态和占位逻辑。
内容的提问来源于stack exchange,提问作者limegik278
相关产品推荐
相关产品推荐

