React Native+Supabase项目报Cannot read property 'isReady' of undefined错误
解决「Cannot read property 'isReady' of undefined, js engine: hermes」错误
核心问题:Hook调用违反React规则
你代码里的const segments = useSegments();写在了函数组件BlogDetailsScreen的外部,而React Hook(包括Expo Router提供的useSegments)必须在函数组件的顶层作用域内调用,不能在组件外部、条件语句或循环中使用。这个错误直接触发了isReady相关的未定义报错。
修复步骤
- 移动Hook调用到组件内部:将
useSegments()的调用移到BlogDetailsScreen组件内部,和其他Hook放在同一层级。 - 修正日期格式化逻辑:当前
formattedTime = date.toDateString()会重复输出日期,改为toLocaleTimeString()获取正确的时间格式。 - 简化ID解析逻辑:优化
id的解析代码,避免冗余的可选链判断。
修正后的完整代码
import React from "react"; import { View, Text, StyleSheet, Image, ScrollView, Pressable, } from "react-native"; import { Link, Stack, useLocalSearchParams, useSegments } from "expo-router"; import { SafeAreaView } from "react-native-safe-area-context"; import { useBlog } from "@/api/blogs"; import Loader from "@/components/Loader"; import { FontAwesome } from "@expo/vector-icons"; const BlogDetailsScreen = () => { const { id } = useLocalSearchParams(); // 将useSegments移至组件内部 const segments = useSegments(); // 简化ID解析逻辑 const blogId = typeof id === "string" ? parseInt(id) : parseInt(id?.[0] ?? "0"); const { data: blog, error, isLoading, } = useBlog(blogId); if (isLoading) { return <Loader />; } if (error) { return <Text>ERROR</Text>; } if (!blog) return <Text>Not found</Text>; const date = new Date(blog.created_at); const formattedDate = date.toLocaleDateString(); // 修正时间格式化方法 const formattedTime = date.toLocaleTimeString(); return ( <SafeAreaView style={{ flex: 1, backgroundColor: "white" }} edges={["top"]}> <Stack.Screen options={{ headerRight: () => ( <Link href={`/(admin)/blogs/create?id=${id}`} asChild> <Pressable> {({ pressed }) => ( <FontAwesome name="pencil" size={25} style={{ marginRight: 15, opacity: pressed ? 0.5 : 1 }} /> )} </Pressable> </Link> ), }} /> <ScrollView style={styles.container}> <View style={styles.contentContainer}> <Image source={{ uri: blog.image }} style={styles.image} /> <Text style={styles.title}>{blog.title}</Text> <Link href={`${segments[0]}/blogs/category`}> <Text>{blog.category}</Text> </Link> <Text style={styles.slug}>{blog.slug}</Text> <Text style={styles.author}>By {blog.author}</Text> <Text style={styles.createdTime}> Published on {formattedDate} {formattedTime} </Text> <Text style={styles.content}>{blog.content}</Text> </View> </ScrollView> </SafeAreaView> ); }; export default BlogDetailsScreen; const styles = StyleSheet.create({ container: { padding: 16, backgroundColor: "white", borderRadius: 20, }, contentContainer: { alignItems: "center", }, category: { borderWidth: 1, padding: 10, borderColor: "black", borderRadius: 20, fontFamily: "Gabarito", margin: 10, }, title: { fontSize: 24, marginBottom: 8, fontFamily: "Gabarito", fontWeight: "bold", }, slug: { fontSize: 16, color: "#666", marginBottom: 8, fontFamily: "Gabarito", }, author: { fontSize: 14, color: "#333", marginBottom: 8, fontFamily: "Gabarito", }, createdTime: { fontSize: 12, color: "#999", marginBottom: 16, fontFamily: "Gabarito", }, content: { fontSize: 16, lineHeight: 24, fontFamily: "Gabarito", }, image: { width: "100%", aspectRatio: 1, borderRadius: 8, marginBottom: 30, }, error: { fontSize: 18, color: "red", }, });
额外检查点
- 确认你的Expo Router版本为最新,旧版本可能存在Hook兼容性问题。
- 验证
useBlogHook的实现,确保它在接收无效ID时能正确处理,避免返回未定义数据。
内容的提问来源于stack exchange,提问作者Aayush Pandey
相关产品推荐
相关产品推荐

