我是React Native的新手,我一直在尝试创建一个视图,其中包含根据我从API提取的数据动态创建的按钮数量。
我的问题之一是返回的数据没有我可以指向的任何名称,例如item.number
。
首先,我尝试做一个<Flatlist/>
,但没有得到想要的设计,像这样:
所以现在我试图用一种不同的方式来制作,但是我总是会收到错误:
无法读取未定义的属性“ 0”
data.json:
{
"sEcho":0,
"iTotalRecords":"75",
"iTotalDisplayRecords":"73",
"aaData":[
[
"1",
"1",
"Consumidor Final",
"999999990",
"",
"",
null,
", ",
"21110000",
"1",
"1",
"1"
],
[
"2",
"1000",
"xxxxxx",
"xxxxx",
"",
"",
null,
", ",
"xxxx",
"15",
"1",
"1"
]
]
}
我如何获取数据;
getClientes = async (token, opcao, search, pag, numRows) => {
var url = "https://xxxx/xxxx/xxx/xxxx/xxx/tabelas/clientes?_token=" + token + "&opcao= " + opcao + "&search=&pag=&numRows=" + numRows;
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.aaData,
isLoading: false,
numRows: responseJson.iTotalDisplayRecords
})
console.log(responseJson.iTotalDisplayRecords + " total");
console.log("CLIENTES: " + responseJson.aaData[0][2]);
console.log(this.state.dataSource[0][2]);
})
.catch((error) => {
console.log(error);
})
}
我如何渲染按钮:
renderClientes = (numRows, data) => {
console.log(numRows + "azxcvb");
console.log(data.length + "render Clientes");
const views = [];
for (let i = 0; i <= numRows; i++) {
for (let j = 0; j <= 11; j++) {
views.push(
<TouchableOpacity style={{ flex: 1, flexDirection: 'row', marginBottom: 3 }} key={i}>
<View style={{ flex: 1, justifyContent: 'center', marginLeft: 5 }}>
<Text style={{ fontSize: 18, color: 'green' }}>
{data[i][j]}
</Text>
</View>
</TouchableOpacity>
);
}
}
return views;
}
然后:
render() {
return (
...
(this.state.numRows != 0) ? this.renderClientes(this.state.numRows, this.state.dataSource) : null)
}
我该如何解决我的问题?如果有更简单的方法可以实现,那是什么?
答案 0 :(得分:1)
看起来您的numRows
是73
,但是您的数组中只有2组行?
通常最好.map
通过一个数组,这样它将自动遍历每个项目。像这样:
renderClientes = (numRows, data) => {
console.log(numRows + "azxcvb");
console.log(data.length + "render Clientes");
return data.map((row, i) =>
row.map((item, j) => (
<TouchableOpacity style={{ flex: 1, flexDirection: 'row', marginBottom: 3 }} key={`${i},${j}`}>
<View style={{ flex: 1, justifyContent: 'center', marginLeft: 5 }}>
<Text style={{ fontSize: 18, color: 'green' }}>
{item}
</Text>
</View>
</TouchableOpacity>
))
);
}
答案 1 :(得分:1)
您收到此错误
错误:无法读取未定义的属性“ 0”,因为您要遍历n个数字数组n + 1次。
要解决此问题,只需像这样分配setState即可:
this.setState({
dataSource: responseJson.aaData,
isLoading: false,
numRows: responseJson.iTotalDisplayRecords - 1
})
正如奥斯汀·格雷科(Austin Greco)所指出的那样,请相信我,我也会去地图,当在React和JavaScript中使用数组时,一切将变得更加容易。
答案 2 :(得分:1)
首先,建议您使用API:
let url = "https://clientes?_token=" + token + "&opcao= ";
永远不要在URL上发送令牌,因为很容易破解它们。您可以在标头上发送隐藏的数据。
正如 @Austin Greco 所说,numRows
是'73'
,但是您的数组只有两组行。我建议将numRows
作为整数而不是字符串发送。
同样,为了从数据构建复杂的接口,您应该使用可以更好地描述数据的对象,而不要像使用数组(aaData
)那样。拍摄您向我们展示的图片:
您可以拥有一个像这样的对象:
{
gt: 'GT 2019/01',
name: 'Luis Filipe Gomes Rodrigues',
total: '179,90 €',
open: true,
nif: 9999999999,
date: '01/01/2019',
}
代替
arr = ['GT 2019/01', 'Luis Filipe Gomes Rodrigues', '179,90 €', true, 9999999999, '01/01/2019']
name = arr[1]
因此,我花了一些时间来制作小吃供您跟进:@abranhe/clients-view看起来像这样:
包装代码:
import React, { Component } from 'react';
import {
View,
Text,
Image,
StyleSheet,
TouchableOpacity,
Dimensions,
ScrollView,
} from 'react-native';
import { AntDesign } from '@expo/vector-icons';
import data from './data.js';
export default class StackOverflowAnswer extends Component {
constructor(props) {
super(props);
this.state = {
data: data,
isLoading: false,
};
}
renderClientLeft(client) {
return (
<View style={styles.clientLeft}>
<Text style={styles.gt}>GT {client.gt}</Text>
<Text style={styles.name} numberOfLines={1}>
{client.name}
</Text>
<Text style={styles.nifAndDate}>NIF: {client.nif}</Text>
<Text style={styles.nifAndDate}>Data: {client.date}</Text>
</View>
);
}
renderClientRight(client) {
let hoursColor = client.open ? '#588f40' : '#4973a3';
let hoursText = client.open ? 'Aberto' : 'Fechado';
return (
<View style={styles.clientRight}>
<View style={{ justifyContent: 'space-around' }}>
<View style={styles.total}>
<Text style={styles.name}>Total:</Text>
<Text style={styles.totalVal}>{client.total}</Text>
</View>
<View style={[{ backgroundColor: hoursColor }, styles.hours]}>
<Text style={styles.hoursText}>{hoursText}</Text>
</View>
</View>
<View style={styles.arrowContainer}>
<AntDesign name="right" color="#bf5e2a" />
</View>
</View>
);
}
renderClient(client) {
return (
<View style={styles.clientContainer}>
<View style={styles.client}>
{this.renderClientLeft(client)}
{this.renderClientRight(client)}
</View>
</View>
);
}
renderClientes = clients => {
return clients.map((client, i) => {
return (
<View key={i} style={styles.clientsSeparator}>
{this.renderClient(client)}
</View>
);
});
};
render() {
const { data } = this.state;
return (
<ScrollView style={styles.container}>
{this.renderClientes(data)}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ededed',
marginTop: 20,
alignItems: 'center',
},
clientContainer: {
width: Dimensions.get('window').width * 0.95,
borderWidth: 1,
borderColor: '#000000',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.4,
shadowRadius: 1,
backgroundColor: '#ffffff',
},
client: {
flexDirection: 'row',
borderRadius: 1,
margin: 4,
},
clientLeft: {
width: '60%',
marginVertical: 5,
},
clientRight: {
justifyContent: 'space-between',
flexDirection: 'row',
height: '100%',
width: '40%',
},
gt: {
fontWeight: '700',
color: '#bf5e2a',
margin: 2,
},
name: {
fontWeight: '700',
margin: 2,
},
nifAndDate: {
color: '#8a8a8a',
margin: 2,
},
arrowContainer: {
justifyContent: 'center',
alignItems: 'center',
},
totalVal: {
color: '#bf5e2a',
marginLeft: 10,
},
total: {
flexDirection: 'row',
},
hours: {
width: '70%',
justifyContent: 'center',
alignItems: 'center',
},
hoursText: {
color: '#ffffff',
margin: 5,
},
clientsSeparator: {
marginBottom: 5,
},
});