在数组中添加新的 json 对象时,视图不刷新。反应本机
View dont refresh when add a new json object in array. REACT NATIVE
程序编译完美,但是当我扫描产品时,它没有在视图中刷新。
我已经为所有产品安装了 mysql xampp。查询条形码时。我得到了产品的详细信息作为响应,并在数组中添加了带有解析对象的 json 响应。
点击TouchableOpacity时视图刷新,稍后扫描产品。
import React, {Component, useState, useEffect} from 'react';
import {Dimensions,Image, View, Text,AsyncStorage, TouchableOpacity, Grid, StyleSheet, ScrollView,ToastAndroid} from 'react-native';
import { SearchBar, Card, Icon } from 'react-native-elements';
import { BarCodeScanner } from 'expo-barcode-scanner';
//import { NumberList } from './NumberList';
const {width, height} = Dimensions.get('window');
const urlApi = "http://192.168.1.24/rst/api/getProduct.php";
const numbers = [1,2,3,4,5,6];
class SaleScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
scan: false,
result: null,
ScanResult: false,
hasPermission: true,
setHasPermission: true,
productos: [],
jwt: null,
};
//this.componentDidMount();
}
async componentDidMount(){
let _jwt = await AsyncStorage.getItem('userToken');
this.setState({
jwt: _jwt
});
}
_searchProduct = async (data) => {
try {
let response = await fetch(urlApi,{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer '+this.state.jwt
},
body: JSON.stringify({
CodiBarra: data
})
});
let responseJson = await response.json();
//console.log(responseJson);
if (responseJson.codibarra === null) {
//console.log("retorna falso");
return false;
}
else
{
if(this.state.productos != null)
{
this.state.productos.push(responseJson[0]);
//this.setState({productos: this.state.productos.push(responseJson[0])})
//console.log(this.state.productos);
}
else
{
this.state.productos.push(responseJson[0]);
}
}
} catch (error) {
console.error(error);
}
};
render(){
const { scan, ScanResult, result, hasPermission, setHasPermission, productos } = this.state;
const activeBarcode = ()=> {
this.setState({
scan: true
})
}
const handleBarCodeScanned = async ({ type, data }) => {
//console.log('scanned data' + data);
this.setState({result: data, scan: false, ScanResult: false});
this._searchProduct(data);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style= {{flex: 1}}>
{productos.length == 0 &&
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
}
{productos.length>0 &&
<View style={{flex:1}}>
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
<View style ={{flex:1,marginTop:20}}>
<ScrollView>
<NumberList products={this.state.productos} />
</ScrollView>
</View>
<View style ={{flex:1,marginTop:20}}>
<View style={{flexDirection:"row", height: 50, width: width, backgroundColor: "green", justifyContent: "center",}}>
<View style = {{ flexDirection:"column"}}>
<Text style = {{ fontSize: 40,color:"white"}}>{"TOTAL: "}</Text>
</View>
<View style={{justifyContent: "center", flexDirection:"row-reverse", paddingRight:20}}>
<Text style = {{ fontSize: 40,color:"white"}}>{result.precioventa}</Text>
</View>
</View>
</View>
</View>
}
{scan &&
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
}
</View>
);
}
}
function NumberList(props) {
console.log("NUMBERLIST")
console.log(props);
const products = props.products;
const listItems = products.map((product) =>
// Correct! Key should be specified inside the array.
<ListItem key={product.key} value={product} />
);
return (
<View>
{listItems}
</View>
);
}
function ListItem(props) {
// Correct! There is no need to specify the key here:
const u = props.value;
return (
<View>
{u &&
<Card>
<View style={{flexDirection:"row"}}>
<Icon
name = "monetization-on"
size = {40}
/>
<View style={{flex:1, flexDirection: "column", paddingTop: 10}}><Text>{u.descripcion}</Text></View>
<View style = {{flexDirection:"row-reverse", paddingTop: 10}}><Text>{u.precioventa}</Text></View>
</View>
</Card>
}
</View>);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'black'
},
containerHome:{
backgroundColor: 'white',
height: height,
width: width,
flexDirection: 'column'
},
cardSales:{
backgroundColor: 'white',
flex: 1,
padding: 15,
borderWidth: 1,
borderRadius: 10,
borderColor: '#ddd',
borderBottomWidth: 7,
//shadowColor: '#000',
shadowColor: "#191919",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop: 20,
},
cardContent:{
flexDirection: 'row-reverse',
fontSize: 50
},
button:{
flexDirection: 'column',
marginTop: 20,
marginLeft: 20,
marginRight: 20,
},
contentActionFast:{
backgroundColor: 'white',
flexDirection: 'row',
alignItems:'center',
justifyContent: 'space-between',
flex:1
}
});
export default SaleScreen;
如果有人能帮助我,我将不胜感激
您的组件没有重新呈现,因为在 _searchProduct
中您正在 this.state.productos.push(responseJson[0]);
更新状态对象,而您应该使用 setState()
。直接修改你现在正在做的状态不会触发重新渲染并可能导致其他问题,这就是为什么你永远不应该这样做并且总是使用 setState()
(或钩子)来更新状态。此处的文档中提到了这一点:https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly.
改为尝试:
this.setState((prevState) => ({
productos: [...prevState.productos, responseJson[0]]
});
程序编译完美,但是当我扫描产品时,它没有在视图中刷新。 我已经为所有产品安装了 mysql xampp。查询条形码时。我得到了产品的详细信息作为响应,并在数组中添加了带有解析对象的 json 响应。
点击TouchableOpacity时视图刷新,稍后扫描产品。
import React, {Component, useState, useEffect} from 'react';
import {Dimensions,Image, View, Text,AsyncStorage, TouchableOpacity, Grid, StyleSheet, ScrollView,ToastAndroid} from 'react-native';
import { SearchBar, Card, Icon } from 'react-native-elements';
import { BarCodeScanner } from 'expo-barcode-scanner';
//import { NumberList } from './NumberList';
const {width, height} = Dimensions.get('window');
const urlApi = "http://192.168.1.24/rst/api/getProduct.php";
const numbers = [1,2,3,4,5,6];
class SaleScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
scan: false,
result: null,
ScanResult: false,
hasPermission: true,
setHasPermission: true,
productos: [],
jwt: null,
};
//this.componentDidMount();
}
async componentDidMount(){
let _jwt = await AsyncStorage.getItem('userToken');
this.setState({
jwt: _jwt
});
}
_searchProduct = async (data) => {
try {
let response = await fetch(urlApi,{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer '+this.state.jwt
},
body: JSON.stringify({
CodiBarra: data
})
});
let responseJson = await response.json();
//console.log(responseJson);
if (responseJson.codibarra === null) {
//console.log("retorna falso");
return false;
}
else
{
if(this.state.productos != null)
{
this.state.productos.push(responseJson[0]);
//this.setState({productos: this.state.productos.push(responseJson[0])})
//console.log(this.state.productos);
}
else
{
this.state.productos.push(responseJson[0]);
}
}
} catch (error) {
console.error(error);
}
};
render(){
const { scan, ScanResult, result, hasPermission, setHasPermission, productos } = this.state;
const activeBarcode = ()=> {
this.setState({
scan: true
})
}
const handleBarCodeScanned = async ({ type, data }) => {
//console.log('scanned data' + data);
this.setState({result: data, scan: false, ScanResult: false});
this._searchProduct(data);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style= {{flex: 1}}>
{productos.length == 0 &&
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
}
{productos.length>0 &&
<View style={{flex:1}}>
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
<View style ={{flex:1,marginTop:20}}>
<ScrollView>
<NumberList products={this.state.productos} />
</ScrollView>
</View>
<View style ={{flex:1,marginTop:20}}>
<View style={{flexDirection:"row", height: 50, width: width, backgroundColor: "green", justifyContent: "center",}}>
<View style = {{ flexDirection:"column"}}>
<Text style = {{ fontSize: 40,color:"white"}}>{"TOTAL: "}</Text>
</View>
<View style={{justifyContent: "center", flexDirection:"row-reverse", paddingRight:20}}>
<Text style = {{ fontSize: 40,color:"white"}}>{result.precioventa}</Text>
</View>
</View>
</View>
</View>
}
{scan &&
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
}
</View>
);
}
}
function NumberList(props) {
console.log("NUMBERLIST")
console.log(props);
const products = props.products;
const listItems = products.map((product) =>
// Correct! Key should be specified inside the array.
<ListItem key={product.key} value={product} />
);
return (
<View>
{listItems}
</View>
);
}
function ListItem(props) {
// Correct! There is no need to specify the key here:
const u = props.value;
return (
<View>
{u &&
<Card>
<View style={{flexDirection:"row"}}>
<Icon
name = "monetization-on"
size = {40}
/>
<View style={{flex:1, flexDirection: "column", paddingTop: 10}}><Text>{u.descripcion}</Text></View>
<View style = {{flexDirection:"row-reverse", paddingTop: 10}}><Text>{u.precioventa}</Text></View>
</View>
</Card>
}
</View>);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'black'
},
containerHome:{
backgroundColor: 'white',
height: height,
width: width,
flexDirection: 'column'
},
cardSales:{
backgroundColor: 'white',
flex: 1,
padding: 15,
borderWidth: 1,
borderRadius: 10,
borderColor: '#ddd',
borderBottomWidth: 7,
//shadowColor: '#000',
shadowColor: "#191919",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop: 20,
},
cardContent:{
flexDirection: 'row-reverse',
fontSize: 50
},
button:{
flexDirection: 'column',
marginTop: 20,
marginLeft: 20,
marginRight: 20,
},
contentActionFast:{
backgroundColor: 'white',
flexDirection: 'row',
alignItems:'center',
justifyContent: 'space-between',
flex:1
}
});
export default SaleScreen;
如果有人能帮助我,我将不胜感激
您的组件没有重新呈现,因为在 _searchProduct
中您正在 this.state.productos.push(responseJson[0]);
更新状态对象,而您应该使用 setState()
。直接修改你现在正在做的状态不会触发重新渲染并可能导致其他问题,这就是为什么你永远不应该这样做并且总是使用 setState()
(或钩子)来更新状态。此处的文档中提到了这一点:https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly.
改为尝试:
this.setState((prevState) => ({
productos: [...prevState.productos, responseJson[0]]
});