【问题标题】:React native make "buttons" dynamically from API从 API 动态反应原生制作“按钮”
【发布时间】:2019-06-22 23:45:45
【问题描述】:

我是 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)
}

如何解决我的问题?如果有更简单的方法可以做到这一点,那是什么?

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    首先推荐您的 API:

    let url = "https://clientes?_token=" + token + "&opcao= ";
    

    永远不要在 URL 上发送令牌,因为很容易破解它们。您可以在标题中发送隐藏数据。


    正如 @Austin Greco 所说,numRows'73',但您的数组只有 2 组行。我建议将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,
      },
    });
    

    【讨论】:

      【解决方案2】:

      看起来您的numRows73,但您的数组中只有两组行?

      通常最好通过数组.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>
          ))
        );
      }
      

      【讨论】:

        【解决方案3】:

        您收到此错误

        错误:无法读取未定义的属性“0”,因为您正在循环 n+1 次 n 数字数组。

        要解决这个问题,只需像这样分配你的 setState:

        this.setState({
                    dataSource: responseJson.aaData,
                    isLoading: false,
                    numRows: responseJson.iTotalDisplayRecords - 1
                })
        

        正如 Austin Greco 已经指出的那样,我也会选择 map,相信我,在 React 和 JavaScript 中使用数组时,它会让一切变得更容易。

        【讨论】:

          猜你喜欢
          • 2021-10-20
          • 1970-01-01
          • 1970-01-01
          • 2018-05-07
          • 2016-01-29
          • 2022-01-19
          • 2019-08-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多