在 React Native 中动态地向 FlatList 添加项目

Add items to FlatList dynamically in React Native

我有一个包含两个项目的 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
  },
});

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 变量并将您的数据存储在其中,以便任何修改都会导致重新渲染。

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

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
  },
});

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

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;

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