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

React Native渲染前更新变量:扫码历史跳转API数据显示异常

问题分析与解决方案

看起来你遇到的是异步数据更新不触发组件重新渲染的问题,根源在于你在render方法里发起网络请求,而且没有用组件的state来管理获取到的二维码数据,导致新数据回来后无法自动刷新页面,总是显示上一次的旧数据。

核心问题拆解:

  • render是纯函数,不应该在这里发起异步请求(比如你的getJSON),每次组件渲染都会重复发起请求,而且请求返回时组件可能已经完成渲染,数据无法同步。
  • 你用了全局变量tabCode来存储数据,它的更新不会触发React的重新渲染机制,所以页面不会更新。
  • 当点击不同的历史ID时,组件的params会变化,但你没有监听这个变化来重新请求对应的数据。

修改后的完整代码:

import React, { Component } from 'react';
import { StyleSheet, View, Text} from 'react-native';
import QRCode from 'react-native-qrcode-svg';

let getJSON = function(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'json';
  xhr.onload = function() {
    var status = xhr.status;
    if (status === 200) {
      callback(null, xhr.response);
    } else {
      callback(status, xhr.response);
    }
  };
  xhr.send();
};

export default class Informations extends Component {
  static navigationOptions = {
    title: 'Informations',
    headerBackTitle: 'Retour',
    headerStyle: {
      backgroundColor: '#557aca', //Sets Header color
    },
    headerTintColor: '#fff', //Sets Header text color
    headerTitleStyle: {
      fontWeight: 'bold', //Sets Header text style
    },
  };

  // 初始化state来存储二维码数据
  state = {
    qrData: null,
    loading: true,
    error: null
  };

  componentDidMount() {
    // 组件挂载时首次请求数据
    this.fetchQrData();
  }

  componentDidUpdate(prevProps) {
    // 当路由参数变化时(点击不同历史ID),重新请求数据
    const prevItemValue = prevProps.navigation.state.params?.itemValue;
    const currentItemValue = this.props.navigation.state.params?.itemValue;
    if (prevItemValue !== currentItemValue) {
      this.fetchQrData();
    }
  }

  // 封装请求数据的方法
  fetchQrData = () => {
    const { params } = this.props.navigation.state;
    const itemValue = params ? params.itemValue : null;
    if (!itemValue) return;

    // 重置状态,显示加载中(可选)
    this.setState({ loading: true, error: null });

    const qrId = JSON.stringify(itemValue).replace(/['"]+/g, '').split(';')[1];
    getJSON(`http://elarnes.fr/get_qrcode.php?idQrCode=${qrId}`, (err, data) => {
      if (err !== null) {
        console.log('Something went wrong: ' + err);
        this.setState({ error: err, loading: false });
      } else {
        this.setState({ qrData: data[0], loading: false });
      }
    });
  };

  render() {
    const { navigate } = this.props.navigation;
    const { params } = this.props.navigation.state;
    const itemValue = params ? params.itemValue : null;
    const { qrData, loading, error } = this.state;

    if (loading) {
      return <View style={styles.container}><Text>加载中...</Text></View>;
    }

    if (error) {
      return <View style={styles.container}><Text>加载失败:{error}</Text></View>;
    }

    return (
      <View style={styles.container}>
        <QRCode 
          value={JSON.stringify(itemValue).replace(/['"]+/g, '')} 
          size={250} 
          color="black" 
          backgroundColor="white" 
          logoSize={30} 
          logoMargin={2} 
          logoBorderRadius={15} 
          logoBackgroundColor="yellow" 
        />
        {qrData && (
          <Text>
            {qrData.code} {qrData.description}
          </Text>
        )}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    justifyContent: 'center',
    alignItems: 'center'
  },
});

关键改动说明:

  1. 用state管理数据:新增qrData、loading、error三个状态,数据更新时通过setState触发组件重新渲染,这样页面就能同步显示最新数据。
  2. 把请求移到生命周期方法:
    • componentDidMount:组件首次挂载时请求数据。
    • componentDidUpdate:监听路由参数的变化,当点击不同的历史ID时,重新请求对应的数据。
  3. 封装请求方法:把getJSON的逻辑封装成fetchQrData,避免代码重复,同时处理加载和错误状态,提升用户体验。
  4. 避免全局变量:去掉全局的tabCode,改用state里的qrData存储数据,避免数据混乱。

这样修改后,每次点击不同的历史ID,组件都会自动请求对应二维码的信息并实时更新页面,不需要手动点击更新按钮啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:12:53