我如何从具有多个对象的平面列表中设置和获取不同的状态和输入

How do i set and get the different states and inputs from a flatlist with multiple objects

好的,我把这个平面列表包含在一个平面列表中,这个平面列表来自内部,包含下拉菜单、输入和按钮,我需要捕获我从它们那里获取的数据,当然还要保存新的数据关于我选择、输入或点击的内容,我不完全确定该怎么做,这是 flatlist

的代码
                <FlatList
              extraData = {this.state}
              data = {this.state.dataSource}
              renderItem = {({item, index}) => {
                return (
                  <View style={{marginTop: hp('2%')}}>
                    <TouchableOpacity style={{
                      alignSelf: 'center',
                      width: wp('95.7%'),
                      height: hp('10%'),
                      backgroundColor: "#ffffff",
                    }} onPress={() => this.toggleExpanded()}>
                      <View style={{flex: 1, flexDirection: 'row', justifyContent: 'space-between'}}>
                        <View style={{flexDirection: 'column', justifyContent: 'center'}}>
                          <Text numberOfLines={2} ellipsizeMode="tail" style={{
                            marginLeft: wp('5%'),
                            width: wp('55%'),//wp('38.2%'), //151
                            //height: hp('2%'), //19
                            fontSize: rfv(16),
                            fontWeight: "500",
                            fontStyle: "normal",
                            textAlign: "left",
                            color: "#707070"
                          }}>{item.Title}</Text>
                          <Text style={{
                            marginLeft: wp('5%'),
                            fontSize: rfv(14),
                            fontWeight: "normal",
                            fontStyle: "normal",
                            textAlign: "left",
                            color: "#c4c4c4"
                          }}>{`ID ${item.Id} - ${item.Cliente}`}</Text>
                        {
                          !item.IsFavorite ?
                          <Text style={{
                            marginLeft: wp('5%'),
                            fontSize: rfv(14),
                            fontWeight: "normal",
                            fontStyle: "italic",
                            textAlign: "left",
                            color: "#c4c4c4"
                          }}>No favorito</Text>
                          : null
                        }
                        </View>
                        <View style={{flexDirection: 'column', justifyContent: 'center'}}>
                          <View style={{flexDirection: 'row', marginRight: wp('3.4%')}}>
                            <Text style={{
                              fontSize: rfv(18),
                              fontWeight: "300",
                              fontStyle: "normal",
                              textAlign: "right",
                              color: "#707070"}}>{`[=10=]h`}</Text>
                            <Image style={{marginTop: hp('1%'), marginLeft: wp('3.7%')}} source={this.state.isCollapsed ? Images.expandible : Images.collapsible}/>
                          </View>
                        </View>
                      </View>
                    </TouchableOpacity>
                    <Collapsible style={{
                      alignSelf: 'center',
                      width: wp('95.7%'),
                      backgroundColor: "#ffffff",}} collapsed={this.state.isCollapsed}>

                    <FlatList
                      //extraData = {this.state}
                      data = {item.ListReportHistoryResponse}//{DataManager.FavoriteList[moment(this.state.selectedDate).format('YYYY-MM-DD')]}
                      renderItem = {({ item, index }) => {
                        return (
                          <View>
                          <View style={{flexDirection: 'row'}}>
                            <Text style={{
                              marginLeft: wp('5%'),
                              fontSize: rfv(14),
                              fontWeight: "normal",
                              fontStyle: "normal",
                              textAlign: "left",
                              color: "#717171"
                            }}>Etapa</Text>
                            <Text style={{
                              marginLeft: wp('42.5%'),
                              fontSize: rfv(14),
                              fontWeight: "normal",
                              fontStyle: "normal",
                              textAlign: "left",
                              color: "#717171"
                            }}>Horas</Text>
                          </View>
                          <View style={{flexDirection: 'row'}}>
                            <ModalDropdown
                              adjustFrame={style => {
                                style.top =(Platform.OS === 'ios' ? style.top : style.top - StatusBar.currentHeight);
                                return style;
                              }}
                              dropdownTextStyle={styles.dropdownTextStyle}
                              dropdownTextHighlightStyle={styles.dropdownTextHighlightStyle}
                              dropdownStyle={styles.dropdownStageStyle}
                              defaultValue={item.Etapa}
                              style={styles.dropStageStyle}
                              textStyle={{
                                padding: 0,
                                margin: 0,
                                fontSize: rfv(16),
                                paddingVertical: hp('1.2%'),
                                fontWeight: 'normal',
                                fontStyle: 'normal',
                                textAlign: 'left',
                                color: item.Etapa /*item.ListReportHistoryResponse[index2].Etapa*/ != 'Selecciona una etapa' ? '#1a1a1a' : '#c4c4c4',
                              }}
                              //onSelect={(index, value) => this.setState({SeleccionClientes: value})}
                              //options={Object.keys(this.state.items)}
                              onSelect={(index, value) => this.setState({SeleccionClientes: value})}
                              options={DataManager.ListEtapa}
                            />
                            <View style={styles.InputContainerHours}>
                              <Text style={styles.InputTextHours}>{item.HorasTrabajadas}</Text>
                            </View>
                            <TouchableOpacity style={{marginTop: hp('0.5%'), marginLeft: wp('5.5%')}} onPress={() => this.props.onSubstract}>
                              <Image source={Images.menos_hora}/>
                            </TouchableOpacity>
                            <TouchableOpacity style={{marginTop: hp('0.5%'), marginLeft: wp('2%')}} onPress={() => this.props.onAdd}>
                              <Image source={Images.mas_hora}/>
                            </TouchableOpacity>
                          </View>
                          <Text style={{
                            fontSize: rfv(14),
                            marginLeft: wp('5%'),
                            fontWeight: "normal",
                            fontStyle: "normal",
                            textAlign: "left",
                            color: "#717171"
                          }}>Observaciones</Text>
                          <Input
                            autoCapitalize="none"
                            maxLength={100}
                            inputContainerStyle={styles.InputContainerComentarioOnBlur}
                            containerStyle={styles.InputComentario}
                            inputStyle={styles.InputTextHoursRInput}
                            placeholderTextColor={'#c4c4c4'}
                            placeholder="(Opcional)"
                            onChangeText={value => this.setState({})}
                          />
                          <TouchableOpacity style={{alignItems: 'flex-end', alignSelf: 'flex-end'}}>
                            <Text style={{
                              marginRight: wp('3.4%'),
                              marginBottom: hp('3%'),
                              fontSize: rfv(14),
                              fontWeight: "normal",
                              fontStyle: "normal",
                              textAlign: "left",
                              color: "#1062cc"
                            }}>Agregar etapa</Text>
                          </TouchableOpacity>
                        </View>
                        )}}/>
                        </Collapsible>
                        </View>
                )
              }}
            />

编辑:更新了平面列表中显示的对象的屏幕截图,我仍然需要帮助才能让它工作

<View style={styles.InputContainerHours}>
<Text style={styles.InputTextHours}>{item.HorasTrabajadas}</Text>
</View>
<TouchableOpacity style={{marginTop: hp('0.5%'), marginLeft: wp('5.5%')}} onPress={() => this.props.onSubstract}>
<Image source={Images.menos_hora}/>
</TouchableOpacity>
<TouchableOpacity style={{marginTop: hp('0.5%'), marginLeft: wp('2%')}} onPress={() => this.props.onAdd}>
<Image source={Images.mas_hora}/>
</TouchableOpacity>

onadd 应该是添加到 item.HorasTrabajadas 的函数,除了当前值之外还有 0.5,而 onsubstract 是相同的但是减去当前值

这是对象

编辑 2:如果 api 包含一个已保存数据的对象,我该如何编辑该新数据?

编辑 3:我添加了一个 github 项目,其中包含该项目最重要的 3 个部分,https://github.com/Vasault/HourReg/tree/develop 包含 3 个文件,最重要的一个 HourRegistration.tsx

编辑 4:无法更改已经来自 api

的数据

您可以使用 index of your array to identify the selected item,当您有每次操作的索引时,您可以根据需要更新每个操作的项目。

假设您有 10 个项目,并且在每个项目上,您都必须更新状态,您可以获得该行的 item and index 并且可以轻松更新状态。

这里有一个简单的例子可以消除你的困惑。 这是一个带有工作示例的小吃

https://snack.expo.io/@waheed25/radarada

import React from 'react';
import { SafeAreaView, View, TextInput, FlatList, StyleSheet, Text } from 'react-native';
import Constants from 'expo-constants';

const DATA = [
  {
    id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
    title: 'First Item',
  },
  {
    id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
    title: 'Second Item',
  },
  {
    id: '58694a0f-3da1-471f-bd96-145571e29d72',
    title: 'Third Item',
  },
];

export default class  App extends React.Component {

  state={
    observacionesInput: []
  }
   onTextObservacionesChange = (text, index) => {
    var { observacionesInput } = this.state
    let myArray = observacionesInput
        myArray[index] = text
    this.setState({observacionesInput: myArray });
  }
  toggleExpanded = () => {
    this.setState({ isCollapsed: !this.state.isCollapsed });  
  };
  render(){
    console.log('state', this.state)
  return (
    <SafeAreaView>
    <Text>Testing</Text>
      <FlatList
        data={DATA}
        renderItem={({ item, index }) => { 
          return(
            <View style={{  marginTop: 20}}>
              <TextInput
               style={{borderColor: 'gray', borderWidth: 1, height: 50,}}
                autoCapitalize="none"
                maxLength={100}
                placeholderTextColor={'#c4c4c4'}
                placeholder="(Opcional)"
                onChangeText={value => this.onTextObservacionesChange(value, index)}
              />
            </View>
          )
        }}
      />
    </SafeAreaView>
  );
  }
}

您可以通过附加 parentIndexchildIndex 来创建动态状态,以声明子项 flatlist

的唯一标识

您可以使用 onChangeValue 将数据保存到 newDataSave 对象中,使用 getDataFromNewSavenewDataSave

中获取数据

注意:你所有保存的数据都是保存在newDataSave对象中。你可以控制台检查它并保存到数据库中。

 onChangeValue = (key, value) => {
    this.setState((prevState) => {
      return {
        newDataSave: {
          ...prevState.newDataSave,
          [key]: value,
        },
      };
    });
  };

  getDataFromNewSave = (key) => {
    try {
      return this.state.newDataSave[key];
    } catch (error) {
      return "";
    }
  };
<Input
                            value={this.getDataFromNewSave(
                              `input${parentIndex}${childIndex}`
                            )}
                            autoCapitalize="none"
                            maxLength={100}
                            inputContainerStyle={
                              styles.InputContainerComentarioOnBlur
                            }
                            containerStyle={styles.InputComentario}
                            inputStyle={styles.InputTextHoursRInput}
                            placeholderTextColor={"#c4c4c4"}
                            placeholder="(Opcional)"
                            onChangeText={(value) => {
                              this.onChangeValue(
                                `input${parentIndex}${childIndex}`,
                                value
                              );
                            }}
                          />

完整代码:

import React, { Component } from "react";
import {
  Text,
  StyleSheet,
  View,
  FlatList,
  TouchableOpacity,
  Image,
  TextInput,
} from "react-native";
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from "react-native-responsive-screen";
import Collapsible from "react-native-collapsible";
import ModalDropdown from "react-native-modal-dropdown";

const Input = TextInput;
const rfv = (value) => {
  return value;
};

const DataManager = {
  ListEtapa: ["a", "b", "c"],
};

const Images = {
  collapsed: require("./assets/icons/app-icon.png"),
  expandible: require("./assets/icons/app-icon.png"),
};

export default class App extends Component {
  state = {
    isCollapsed: false,
    dataSource: [
      {
        Id: "1",
        Title: "abc1",
        Cliente: "abc1",
        IsFavorite: false,
        ListReportHistoryResponse: [
          { Etapa: "abc1", HorasTrabajadas: "abcabc1" },
          { Etapa: "cde1", HorasTrabajadas: "cdecde1" },
        ],
      },
      {
        Id: "2",
        Title: "abc2",
        Cliente: "abc2",
        IsFavorite: false,
        ListReportHistoryResponse: [
          { Etapa: "abc2", HorasTrabajadas: "abcabc2" },
          { Etapa: "cde2", HorasTrabajadas: "cdecde2" },
        ],
      },
    ],
    newDataSave: {},
  };

  onChangeValue = (key, value) => {
    this.setState((prevState) => {
      return {
        newDataSave: {
          ...prevState.newDataSave,
          [key]: value,
        },
      };
    });
  };

  getDataFromNewSave = (key) => {
    try {
      return this.state.newDataSave[key];
    } catch (error) {
      return "";
    }
  };

  render() {
    return (
      <View>
        <FlatList
          extraData={this.state}
          data={this.state.dataSource}
          renderItem={({ item, index: parentIndex }) => {
            return (
              <View style={{ marginTop: hp("2%") }}>
                <TouchableOpacity
                  style={{
                    alignSelf: "center",
                    width: wp("95.7%"),
                    height: hp("10%"),
                    backgroundColor: "#ffffff",
                  }}
                  onPress={() => this.toggleExpanded()}
                >
                  <View
                    style={{
                      flex: 1,
                      flexDirection: "row",
                      justifyContent: "space-between",
                    }}
                  >
                    <View
                      style={{
                        flexDirection: "column",
                        justifyContent: "center",
                      }}
                    >
                      <Text
                        numberOfLines={2}
                        ellipsizeMode="tail"
                        style={{
                          marginLeft: wp("5%"),
                          width: wp("55%"), //wp('38.2%'), //151
                          //height: hp('2%'), //19
                          fontSize: rfv(16),
                          fontWeight: "500",
                          fontStyle: "normal",
                          textAlign: "left",
                          color: "#707070",
                        }}
                      >
                        {item.Title}
                      </Text>
                      <Text
                        style={{
                          marginLeft: wp("5%"),
                          fontSize: rfv(14),
                          fontWeight: "normal",
                          fontStyle: "normal",
                          textAlign: "left",
                          color: "#c4c4c4",
                        }}
                      >{`ID ${item.Id} - ${item.Cliente}`}</Text>
                      {!item.IsFavorite ? (
                        <Text
                          style={{
                            marginLeft: wp("5%"),
                            fontSize: rfv(14),
                            fontWeight: "normal",
                            fontStyle: "italic",
                            textAlign: "left",
                            color: "#c4c4c4",
                          }}
                        >
                          No favorito
                        </Text>
                      ) : null}
                    </View>
                    <View
                      style={{
                        flexDirection: "column",
                        justifyContent: "center",
                      }}
                    >
                      <View
                        style={{
                          flexDirection: "row",
                          marginRight: wp("3.4%"),
                        }}
                      >
                        <Text
                          style={{
                            fontSize: rfv(18),
                            fontWeight: "300",
                            fontStyle: "normal",
                            textAlign: "right",
                            color: "#707070",
                          }}
                        >{`[=12=]h`}</Text>
                        <Image
                          style={{
                            marginTop: hp("1%"),
                            marginLeft: wp("3.7%"),
                          }}
                          source={
                            this.state.isCollapsed
                              ? Images.expandible
                              : Images.collapsible
                          }
                        />
                      </View>
                    </View>
                  </View>
                </TouchableOpacity>
                <Collapsible
                  style={{
                    alignSelf: "center",
                    width: wp("95.7%"),
                    backgroundColor: "#ffffff",
                  }}
                  collapsed={this.state.isCollapsed}
                >
                  <FlatList
                    //extraData = {this.state}
                    data={item.ListReportHistoryResponse} //{DataManager.FavoriteList[moment(this.state.selectedDate).format('YYYY-MM-DD')]}
                    renderItem={({ item, index: childIndex }) => {
                      return (
                        <View>
                          <View style={{ flexDirection: "row" }}>
                            <Text
                              style={{
                                marginLeft: wp("5%"),
                                fontSize: rfv(14),
                                fontWeight: "normal",
                                fontStyle: "normal",
                                textAlign: "left",
                                color: "#717171",
                              }}
                            >
                              Etapa
                            </Text>
                            <Text
                              style={{
                                marginLeft: wp("42.5%"),
                                fontSize: rfv(14),
                                fontWeight: "normal",
                                fontStyle: "normal",
                                textAlign: "left",
                                color: "#717171",
                              }}
                            >
                              Horas
                            </Text>
                          </View>
                          <View style={{ flexDirection: "row" }}>
                            <ModalDropdown
                              adjustFrame={(style) => {
                                style.top =
                                  Platform.OS === "ios"
                                    ? style.top
                                    : style.top - StatusBar.currentHeight;
                                return style;
                              }}
                              dropdownTextStyle={styles.dropdownTextStyle}
                              dropdownTextHighlightStyle={
                                styles.dropdownTextHighlightStyle
                              }
                              dropdownStyle={styles.dropdownStageStyle}
                              defaultValue={this.getDataFromNewSave(
                                `SeleccionClientes${parentIndex}${childIndex}`
                              )}
                              style={styles.dropStageStyle}
                              textStyle={{
                                padding: 0,
                                margin: 0,
                                fontSize: rfv(16),
                                paddingVertical: hp("1.2%"),
                                fontWeight: "normal",
                                fontStyle: "normal",
                                textAlign: "left",
                                color:
                                  item.Etapa /*item.ListReportHistoryResponse[index2].Etapa*/ !=
                                  "Selecciona una etapa"
                                    ? "#1a1a1a"
                                    : "#c4c4c4",
                              }}
                              //onSelect={(index, value) => this.setState({SeleccionClientes: value})}
                              //options={Object.keys(this.state.items)}
                              onSelect={(i, value) =>
                                // this.setState({ SeleccionClientes: value })
                                this.onChangeValue(
                                  `SeleccionClientes${parentIndex}${childIndex}`,
                                  value
                                )
                              }
                              options={DataManager.ListEtapa}
                            />
                            <View style={styles.InputContainerHours}>
                              <Text style={styles.InputTextHours}>
                                {item.HorasTrabajadas}
                              </Text>
                            </View>
                            <TouchableOpacity
                              style={{
                                marginTop: hp("0.5%"),
                                marginLeft: wp("5.5%"),
                              }}
                              onPress={() => this.props.onSubstract}
                            >
                              <Image source={Images.menos_hora} />
                            </TouchableOpacity>
                            <TouchableOpacity
                              style={{
                                marginTop: hp("0.5%"),
                                marginLeft: wp("2%"),
                              }}
                              onPress={() => this.props.onAdd}
                            >
                              <Image source={Images.mas_hora} />
                            </TouchableOpacity>
                          </View>
                          <Text
                            style={{
                              fontSize: rfv(14),
                              marginLeft: wp("5%"),
                              fontWeight: "normal",
                              fontStyle: "normal",
                              textAlign: "left",
                              color: "#717171",
                            }}
                          >
                            Observaciones
                          </Text>
                          <Input
                            value={this.getDataFromNewSave(
                              `input${parentIndex}${childIndex}`
                            )}
                            autoCapitalize="none"
                            maxLength={100}
                            inputContainerStyle={
                              styles.InputContainerComentarioOnBlur
                            }
                            containerStyle={styles.InputComentario}
                            inputStyle={styles.InputTextHoursRInput}
                            placeholderTextColor={"#c4c4c4"}
                            placeholder="(Opcional)"
                            onChangeText={(value) => {
                              this.onChangeValue(
                                `input${parentIndex}${childIndex}`,
                                value
                              );
                            }}
                          />
                          <TouchableOpacity
                            style={{
                              alignItems: "flex-end",
                              alignSelf: "flex-end",
                            }}
                          >
                            <Text
                              style={{
                                marginRight: wp("3.4%"),
                                marginBottom: hp("3%"),
                                fontSize: rfv(14),
                                fontWeight: "normal",
                                fontStyle: "normal",
                                textAlign: "left",
                                color: "#1062cc",
                              }}
                            >
                              Agregar etapa
                            </Text>
                          </TouchableOpacity>
                        </View>
                      );
                    }}
                  />
                </Collapsible>
              </View>
            );
          }}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({});

已解决,方法更好更简单

在每个输入、下拉列表等上设置一个函数并传递 3 个参数 onChangeText={value => this.onChangeTextObservaciones(parentIndex, childIndex, value)

parentIndex(来自 flatlist 外部的那个),childIndex(来自内部的那个),以及您正在编辑的值(空白与否)

const onChangeTextObservaciones = (indexOutside, indexInside, value) => {
    this.dataList[indexOutside].ListReportHistoryResponse[indexInside].Title = value;
    this.setState({displayDay: this.dataList});
}

从该对象的特定元素更改特定值,并用新值更改它,最后用新值更改整个新对象。

我的一个朋友意识到了这一点