简体   繁体   English

在 React Native 中动态添加项目到 FlatList

[英]Add items to FlatList dynamically in React Native

I have a FlatList with two items.我有一个包含两个项目的 FlatList。 I need to append this list with another elements.我需要 append 这个列表与另一个元素。 When the user clicks on the button, the data from the text inputs should appear in the end of the FlatList.当用户单击按钮时,来自文本输入的数据应出现在 FlatList 的末尾。 So, I've tried to push data object to the end of the list's array, but new item replaces the last one.因此,我尝试将数据 object 推送到列表数组的末尾,但新项目替换了最后一个。

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

You are just changing the listElements array.您只是在更改 listElements 数组。 This will NOT trigger the re rendering of the component and hence the flat list will be unchanged.这不会触发组件的重新渲染,因此平面列表将保持不变。

Create a state variable in the component and store your data in that so that any modification results in re rendering.在组件中创建一个state变量并将您的数据存储在其中,以便任何修改都会导致重新渲染。

I fixed the problem of replacing elements by changing array into a state variable.我通过将数组更改为 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
  },
});

i fixed it by defining the array outside the export function我通过在导出 function 之外定义数组来修复它

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;

this was part of an larger app, but it should do the trick, I hope it helps这是一个更大的应用程序的一部分,但它应该可以解决问题,我希望它有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM