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' }, });
关键改动说明:
- 用state管理数据:新增
qrData、loading、error三个状态,数据更新时通过setState触发组件重新渲染,这样页面就能同步显示最新数据。 - 把请求移到生命周期方法:
componentDidMount:组件首次挂载时请求数据。componentDidUpdate:监听路由参数的变化,当点击不同的历史ID时,重新请求对应的数据。
- 封装请求方法:把
getJSON的逻辑封装成fetchQrData,避免代码重复,同时处理加载和错误状态,提升用户体验。 - 避免全局变量:去掉全局的
tabCode,改用state里的qrData存储数据,避免数据混乱。
这样修改后,每次点击不同的历史ID,组件都会自动请求对应二维码的信息并实时更新页面,不需要手动点击更新按钮啦。
内容的提问来源于stack exchange,提问作者Davi
相关产品推荐
相关产品推荐

