【问题标题】:Add items to FlatList dynamically in React Native在 React Native 中动态添加项目到 FlatList
【发布时间】:2020-07-18 03:12:55
【问题描述】:

我有一个包含两个项目的 FlatList。我需要在这个列表中附加其他元素。当用户单击按钮时,来自文本输入的数据应出现在 FlatList 的末尾。因此,我尝试将数据对象推送到列表数组的末尾,但新项目替换了最后一个。

import React, { useState } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';

export default function HomeScreen() {

  var initialElements = [
    { id : "0", text : "Object 1"},
    { id : "1", text : "Object 2"},
  ]

  const [exampleState, setExampleState] = useState(initialElements);
  const [idx, incr] = useState(2);

  const addElement = () => {
    var newArray = [...initialElements , {id : toString(idx), text: "Object " + (idx+1) }];
    initialElements.push({id : toString(idx), text: "Object " + (idx+1) });
    incr(idx + 1);
    setExampleState(newArray);
  }

  return (
    <View style={styles.container}>
        <FlatList
            keyExtractor = {item => item.id}  
            data={exampleState}
            renderItem = {item => (<Text>{item.item.text}</Text>)} />
        <Button
          title="Add element"
          onPress={addElement} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    width: '100%',
    borderWidth: 1
  },
});

【问题讨论】:

    标签: javascript arrays react-native listview react-native-flatlist


    【解决方案1】:

    我通过在导出函数之外定义数组来修复它

    import React, { useState } from 'react'
    import { StyleSheet, View, TextInput, TouchableOpacity, Text, FlatList } from 'react-native'
    
    let tipArray = [
        {key: '1', tip: 20},
        {key: '2', tip: 12}
    ]
    
    const screen = function tipInputScreen( {navigation} ) {
        
        const [ tip, setTip ] = useState('')
        
        const addTip = ()=>{
            if(tip == "")return
    
            tipArray.push({key: (tipArray.length + 1).toString(), tip})
            setTip('')
        }
    
        const logInput = (input)=>{
            setTip(input)
        }
    
        const renderTip = ({ item }) => {
            return(
            <TouchableOpacity style={styles.listItem}>
                <Text style={styles.buttonText}>{`${item.tip} $`}</Text>
            </TouchableOpacity>)
        }
    
        return (
            <View
            style={styles.background}>
                <TextInput
                style={styles.input}
                keyboardType={'number-pad'}
                keyboardAppearance={'dark'}
                onChangeText={logInput}
                value={tip}
                />
    
                <TouchableOpacity
                style={styles.redButton}
                onPress={addTip}>
                    <Text style={styles.buttonText}>Add Tip</Text>
                </TouchableOpacity>
            
                <FlatList
                data={tipArray}
                renderItem={renderTip}
                style={styles.flatList}
                />
            </View>
        )
    }
    
    const styles = StyleSheet.create({
        background: {
            backgroundColor: 'grey',
            paddingTop: Platform.OS === "android" ? 25:0,
            width: '100%',
            height: '100%',
            alignItems: 'center'
        },
        input: {
            marginTop:40,
            color:'white',
            fontSize:30,
            backgroundColor: "#2e2a2a",
            height: 50,
            width: '90%',
            textDecorationColor: "white",
            borderColor: 'black',
            borderWidth: 2
        },
        flatList:{
            width: "100%"
        },
        listItem: {
            width: "90%",
            height: 50,
            backgroundColor: "#2e2e2e",
            borderRadius: 25,
            marginVertical: 4,
            marginHorizontal: "5%",
            justifyContent: "center"
        },
        listItemTitle: {
            color: "white",
            textAlign: "center",
            fontSize: 18
        },
        redButton: {
            justifyContent: "center",
            width: "90%",
            height: 50,
            backgroundColor: "red",
            borderRadius: 25,
            marginHorizontal: 20,
            marginVertical: 10
        },
        buttonText: {
            color: "white",
            textAlign: "center",
            fontSize: 18
        }
    })
    
    export default screen;
    

    这是一个更大的应用程序的一部分,但它应该可以解决问题,我希望它有所帮助

    【讨论】:

      【解决方案2】:

      我通过将数组更改为状态变量来解决替换元素的问题。

      import React, { useState } from 'react';
      import { Text, View, StyleSheet, Button } from 'react-native';
      import { FlatList } from 'react-native-gesture-handler';
      
      export default function HomeScreen() {
      
        const [initialElements, changeEl]  = useState([
          { id : "0", text : "Object 1"},
          { id : "1", text : "Object 2"},
        ]);
      
        const [exampleState, setExampleState] = useState(initialElements);
        const [idx, incr] = useState(2);
      
        const addElement = () => {
          var newArray = [...initialElements , {id : idx, text: "Object " + (idx+1) }];
          incr(idx + 1);
          console.log(initialElements.length);
          setExampleState(newArray);
          changeEl(newArray);
        }
      
        return (
          <View style={styles.container}>
              <FlatList
                  keyExtractor = {item => item.id}  
                  data={exampleState}
                  renderItem = {item => (<Text>{item.item.text}</Text>)} />
              <Button
                title="Add element"
                onPress={addElement} />
          </View>
        );
      }
      
      const styles = StyleSheet.create({
        container: {
          flex: 1,
          backgroundColor: '#fff',
          width: '100%',
          borderWidth: 1
        },
      });
      

      【讨论】:

        【解决方案3】:

        import React, { useState } from 'react';
        import { Text, View, StyleSheet, Button } from 'react-native';
        import { FlatList } from 'react-native-gesture-handler';
        
        export default function HomeScreen() {
        
          var initialElements = [
            { id : "0", text : "Object 1"},
            { id : "1", text : "Object 2"},
          ]
        
          const [exampleState, setExampleState] = useState(initialElements)
        
          const addElement = () => {
            var newArray = [...initialElements , {id : "2", text: "Object 3"}];
            setExampleState(newArray);
          }
        
          return (
            <View style={styles.container}>
                <FlatList
                    keyExtractor = {item => item.id}  
                    data={exampleState}
                    renderItem = {item => (<Text>{item.item.text}</Text>)} />
                <Button
                  title="Add element"
                  onPress={addElement} />
            </View>
          );
        }
        
        const styles = StyleSheet.create({
          container: {
            flex: 1,
            backgroundColor: '#fff',
            width: '100%',
            borderWidth: 1
          },
        });

        您只是在更改 listElements 数组。这不会触发组件的重新渲染,因此平面列表将保持不变。

        在组件中创建一个 state 变量并将您的数据存储在其中,以便任何修改都会导致重新渲染。

        【讨论】:

        • 对不起,我是 React Native 开发的新手。如何在数组中创建状态变量?
        • 好的,它有效。但是当我在添加第三个元素之后添加新元素时,它会替换最后一个元素并且不会附加到列表中。所以,我不能在列表中添加超过 3 个项目。
        • 我使用了不同的 id,但只有一项出现在列表底部。我更新了我的答案,你可以查看我的新代码。