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

React Native圣经应用动态API调用及页面刷新问题求助

问题分析与解决方案

核心问题1:route.params未定义

代码错误点:

  1. Verse.js未正确获取路由参数:你注释掉了const { verseReference } = route.params;,但在JSX模板中直接使用{ verseReference },导致变量未定义报错。
  2. Card.js错误使用类组件语法:在函数组件里写this.state = { verseReference: "Test" };,函数组件不支持this.state,这行代码无效且会引发运行时错误。
  3. Card.js异步state更新用法错误:setSelectedVerseReference(verseReference)后立即console.log(selectedVerseReference),由于useState是异步更新,这里打印的始终是旧值,没有实际意义。

修复方案:

  • 移除Card.js中的this.state代码块。
  • 在Verse.js中正确获取路由参数,添加可选链避免参数未定义时的报错。

核心问题2:切换经文后详情页不重新加载

代码错误点:

  1. 未监听路由参数变化:仅在组件挂载时读取一次AsyncStorage和调用API,从Card页面切换不同经文导航过来时,路由参数变化但组件无响应。
  2. AsyncStorage冗余使用:已经通过路由传递参数,没必要再用AsyncStorage中转,反而增加状态同步复杂度。
  3. useEffect依赖错误:第二个useEffect依赖selectedVerseReference,但该state从未被赋值,永远不会触发;第一个useEffect依赖空数组,仅执行一次。
  4. API请求存在语法错误:Verse.js的fetch请求中引用了未定义的data变量,会导致请求失败。

修复方案:

  • 直接使用路由参数作为API请求依据,移除AsyncStorage的冗余逻辑。
  • 监听route.params变化,参数更新时重新调用API。
  • 修正API请求错误,移除未定义的body参数(GET请求无需body)。

修复后的Card.js代码

import React from "react";
import { StyleSheet, TouchableWithoutFeedback } from 'react-native';
import { Block, Text, theme } from 'galio-framework';
import { argonTheme } from '../constants';
import PropTypes from 'prop-types';
import { useNavigation } from '@react-navigation/native';

const Card = ({ item, horizontal, full, style, ctaColor, imageStyle }) => {
  
  const navigation = useNavigation();

  const viewVerse = (verseReference) => {
    // 直接通过路由传递参数,无需AsyncStorage中转
    navigation.navigate(item.link, { verseReference });
  }

  const imageStyles = [
    full ? styles.fullImage : styles.horizontalImage,
    imageStyle
  ];

  const cardContainer = [styles.card, styles.shadow, style];
  const imgContainer = [
    styles.imageContainer,
    horizontal ? styles.horizontalStyles : styles.verticalStyles,
    styles.shadow
  ];

  return (
    <Block row={horizontal} card flex style={cardContainer}>
      <TouchableWithoutFeedback onPress={() => console.log('OK Pressed')}>
        <Block flex style={imgContainer}></Block>
      </TouchableWithoutFeedback>
      <TouchableWithoutFeedback onPress={() => viewVerse(item.kjv_verse_keyphrase)}>
        <Block flex space="between" style={styles.cardDescription}>
          <Text size={16} style={styles.cardTitle}>{item.title}</Text>
          <Text size={12} muted={!ctaColor} color={ctaColor || argonTheme.COLORS.ACTIVE} bold>{item.link}</Text>
          <Text size={12} muted={!ctaColor} color={ctaColor || argonTheme.COLORS.ACTIVE} bold>{item.kjv_verse_keyphrase}</Text>
        </Block>
      </TouchableWithoutFeedback>
    </Block>
  );
}

Card.propTypes = {
  item: PropTypes.object,
  navigation: PropTypes.object,
  horizontal: PropTypes.bool,
  full: PropTypes.bool,
  ctaColor: PropTypes.string,
  imageStyle: PropTypes.any,
}

// 保留你的样式代码
const styles = StyleSheet.create({
  card: {
    // 原样式内容
  },
  // 其他样式...
});

export default Card;

修复后的Verse.js代码

import React, { useEffect, useState } from "react";
import { useNavigation, useRoute } from "@react-navigation/native";
import { View, StyleSheet, Dimensions, ScrollView, Image, ImageBackground, ActivityIndicator } from "react-native";
import { Block, Text, theme } from "galio-framework";
import { Button } from "../components";
import { Images, argonTheme } from "../constants";
import { HeaderHeight } from "../constants/utils";
import RenderHtml from 'react-native-render-html';

// Environment & Screen
import { REACT_APP_KJV_API_KEY } from '@env';
const { width, height } = Dimensions.get("screen");

const thumbMeasure = (width - 48 - 32) / 3;

const Verse = () => {
  const navigation = useNavigation();
  const route = useRoute();  

  // 从路由参数获取经文引用,添加可选链避免参数未定义报错
  const { verseReference } = route.params || {};

  const [isLoading, setIsLoading] = useState(true);
  const [verseContent, setVerseContent] = useState(null);  

  // 监听路由参数变化,参数更新时重新请求API
  useEffect(() => {
    if (!verseReference) return;

    const fetchVerseData = async () => {
      setIsLoading(true);
      try {
        const fullURLstructure = constructApiUrl(verseReference);  
        console.log("Full URL Structure: " + fullURLstructure);
        
        const response = await fetch(fullURLstructure, {
          headers:{
            'api-key': REACT_APP_KJV_API_KEY,
          },
        });
        
        if (!response.ok) throw new Error('API请求失败');
        const data = await response.json();
        setVerseContent(data);
      } catch (error) {
        console.error('Error fetching verse data:', error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchVerseData();
  }, [verseReference]); // 依赖路由参数,参数变化时触发请求

  const constructApiUrl = (verseValue) => {
    const baseBibleURL = 'https://api.bibliosexample.com/v3/xljsnfuoalkls/passages/';  
    return `${baseBibleURL}${verseValue}`;
  };
   
  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  if (!verseContent?.data) {
    return (
      <View style={{ flex:1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>Verse data not found.</Text>
      </View>
    );
  }

  const source = {
    html: verseContent.data.content
  };

  return (
    <Block flex style={styles.profile}>
      <Block flex>
        <ImageBackground source={Images.ProfileBackground} style={styles.profileContainer} imageStyle={styles.profileBackground}>
          <ScrollView showsVerticalScrollIndicator={false} style={{ width, marginTop: '10%' }} >
            <Block flex style={styles.profileCard}>
              <Block flex>
                <Block middle style={styles.nameInfo}>
                  <Text bold size={28} color="#32325D">{ verseReference || 'Unknown Verse' }</Text>
                  <Text size={16} color="#32325D" style={{ marginTop: 10 }}>{verseContent.data.reference}</Text>
                </Block>

                <Block middle style={{ marginTop: 30, marginBottom: 16 }}><Block style={styles.divider} /></Block>
                
                <Block middle>
                  <RenderHtml contentWidth={width} source={source}/>
                  <Button color="transparent" textStyle={{color: "#233DD2",fontWeight: "500",fontSize: 16}}>
                    Read Full Verse
                  </Button>
                </Block>
              </Block>
            </Block>
          </ScrollView>
        </ImageBackground>
      </Block>
    </Block>
  );
};

// 保留你的样式代码
const styles = StyleSheet.create({
  profile: {
    // 原样式内容
  },
  // 其他样式...
});

export default Verse;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:27:05