简体   繁体   中英

React Add and Delete Row dynamically

In the below code, when I am trying to add row with addRow Icon (faPlus) the row is getting added and the state is updated with the number of rows.

When I am trying to delete, the state is not updated with all the rows, it is always less by 1 row.

This is the code for adding a row where three text box and one delete button is added. This code updates the state with number of rows added.

 const updateRowData = () => {
        let rows = [];
        console.log('inside update row data');
        setrowCount(prevCount => prevCount + 1)
        for (let index = 0; index < rowCount; index++) {
            rows.push(
                <DataTable.Row key={index} id={index}>
                    <DataTable.Cell>
                        <Checkbox status={'checked'} />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Key" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Key${index+1}`, itemValue)}
                                />        
                            )}
                        name={`Key${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Value" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Value${index+1}`, itemValue)}
                                />
                            )}
                        name={`Value${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Description" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Description${index+1}`, itemValue)}
                                />
                            )}
                        name={`Description${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <TouchableOpacity onPress = {() => removeItem(index)}>
                            <FontAwesomeIcon icon={faBackspace} size={20} style={[KeyPairRowStyle.iconStyle]}/>
                        </TouchableOpacity>
                    </DataTable.Cell>
                </DataTable.Row>
            )
        }
        // return rows;
        setRowsState(rows)
        console.log('row state in update row data ,',rowsState.length, rowsState);
        console.log("After", rows.length);
        console.log("This row should update", rows);
    }

This is remove row, where the selected row should be deleted based on index but the state here always starts with (rowInState - 1). Current state is not reflected while deleting.

const removeItem = (i) => {
        console.log("tableRowsWhileDelete", rowsState.length);
        let a = [...rowsState]
        console.log("a", a);
        const reducedArr = a.filter((item, itemIndex) => {
            if(itemIndex !== i)
                return item  
        })

        console.log("reducedArr", reducedArr);
        setRowsState(reducedArr)
        setrowCount(reducedArr.length + 1)
    }

Prints header of row with add button.

    return (
        <View>
            <DataTable>
                <DataTable.Header>
                    <DataTable.Title></DataTable.Title>
                    <DataTable.Title>Key</DataTable.Title>
                    <DataTable.Title>Value</DataTable.Title>
                    <DataTable.Title>Description</DataTable.Title>
                    <DataTable.Title>
                        <TouchableOpacity onPress={updateRowData}>
                            <FontAwesomeIcon icon={faPlus}/>
                        </TouchableOpacity>
                    </DataTable.Title>
                </DataTable.Header>
                <View>
                    {rowsState}
                </View>
            </DataTable>
        </View>
    )
}

Full Code

import React, { useEffect, useState } from 'react'
import { StyleSheet, Text, TextInput, View } from 'react-native'
// import { Table, Row, Rows, Cell } from 'react-native-table-component';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import TableRow from './TableRow'
import { TouchableOpacity } from 'react-native-gesture-handler'
import KeyPairCell from './KeyPairCell'
import { DataTable } from 'react-native-paper'
import { Checkbox } from 'react-native-paper'
import { faBackspace } from '@fortawesome/free-solid-svg-icons'
import KeyPairRow from './KeyPairRow'

import { Controller } from 'react-hook-form'

function KeyPair({control, setValue, resetField}) {

    const [rowCount, setrowCount] = useState(1)

    const [rowsState, setRowsState] = useState([])
    

    const updateCount = () => {
        setrowCount(prevCount => prevCount - 1);
    }

    const removeItem = (i) => {
        console.log("tableRowsWhileDelete", rowsState.length);
        let a = [...rowsState]
        console.log("a", a);
        const reducedArr = a.filter((item, itemIndex) => {
            if(itemIndex !== i)
                return item  
        })

        console.log("reducedArr", reducedArr);
        setRowsState(reducedArr)
        setrowCount(reducedArr.length + 1)
    }

    const printRow = () => {
        console.log(rowsState);
    }


    const updateRowData = () => {
        let rows = [];
        console.log('inside update row data');
        setrowCount(prevCount => prevCount + 1)
        for (let index = 0; index < rowCount; index++) {
            rows.push(
                <DataTable.Row key={index} id={index}>
                    <DataTable.Cell>
                        <Checkbox status={'checked'} />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Key" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Key${index+1}`, itemValue)}
                                />        
                            )}
                        name={`Key${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Value" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Value${index+1}`, itemValue)}
                                />
                            )}
                        name={`Value${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Description" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Description${index+1}`, itemValue)}
                                />
                            )}
                        name={`Description${index+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <TouchableOpacity onPress = {() => removeItem(index)}>
                            <FontAwesomeIcon icon={faBackspace} size={20} style={[KeyPairRowStyle.iconStyle]}/>
                        </TouchableOpacity>
                    </DataTable.Cell>
                </DataTable.Row>
            )
        }
        // return rows;
        setRowsState(rows)
        console.log('row state in update row data ,',rowsState.length, rowsState);
        console.log("After", rows.length);
        console.log("This row should update", rows);
    }

    return (
        <View>
            <DataTable>
                <DataTable.Header>
                    <DataTable.Title></DataTable.Title>
                    <DataTable.Title>Key</DataTable.Title>
                    <DataTable.Title>Value</DataTable.Title>
                    <DataTable.Title>Description</DataTable.Title>
                    <DataTable.Title>
                        <TouchableOpacity onPress={updateRowData}>
                            <FontAwesomeIcon icon={faPlus}/>
                        </TouchableOpacity>
                    </DataTable.Title>
                </DataTable.Header>
                <View>
                    {rowsState}
                </View>
            </DataTable>
        </View>
    )
}

const KeyPairRowStyle = StyleSheet.create({
    iconStyle: {
        // paddingRight: 10,
        // paddingLeft: 10,
        color: "#dc3545",
    }
})

const KeyPairStyle = StyleSheet.create({
    KeyPairContainer: {
        
    },
    iconStyle: {
        // paddingRight: 10,
        // paddingLeft: 10,
        padding: 20,
        color: "#6c757d",
    },
    textStyle: {
        fontSize: 16,
        fontWeight: "600",
        padding: 20,
        paddingLeft: 60
    },
    KeyPairHeader: {
        // width: 1124,
        flexDirection: "row",
        flex: 1,
        justifyContent: "space-between"
    },
    cellStyle: {

    },
    textInput: {
    }
})

export default KeyPair

So, I solve the problem by implementing DrewReese suggestion in my own way. So, on addition, I am updating my array with an object having my row data (empty), and on the basis of this array, I am mapping the JSX now.

Here's my code in case someone needs it in future. Adios.

import React, { useEffect, useState } from 'react'
import { StyleSheet, Text, TextInput, View } from 'react-native'
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { TouchableOpacity } from 'react-native-gesture-handler'
import { DataTable } from 'react-native-paper'
import { Checkbox } from 'react-native-paper'
import { faBackspace } from '@fortawesome/free-solid-svg-icons'
import { Controller } from 'react-hook-form'

function KeyPair({control, setValue, resetField}) {

    const [pairState, setPairState] = useState([]);
    const [countAdd, setCountAdd] = useState(0);
    
    const pair = {
        id: countAdd,
        key: 1,
        description: 'desc' + countAdd,
        value: 'value' + countAdd,
      };

      const addHandler = () => {
        setCountAdd((prev) => prev + 1);
        const pairArray = [];
        pairArray.push(pair);
        setPairState(pairState.concat(pairArray));
      };

      const deleteHandler = (id) => {
        let a = [...pairState];
        let ind = a.findIndex((item, i) => item.id == id);
        a.splice(ind, 1);
        setPairState(a);
      };

    return (
        <View>
            <DataTable>
                <DataTable.Header>
                    <DataTable.Title></DataTable.Title>
                    <DataTable.Title>Key</DataTable.Title>
                    <DataTable.Title>Value</DataTable.Title>
                    <DataTable.Title>Description</DataTable.Title>
                    <DataTable.Title>
                        <TouchableOpacity onPress={addHandler}>
                            <FontAwesomeIcon icon={faPlus}/>
                        </TouchableOpacity>
                    </DataTable.Title>
                </DataTable.Header>
                {pairState && pairState.map((pair, i) => {
                    return (
                        <DataTable.Row key={pair.id} id={pair.id}>
                    <DataTable.Cell>
                        <Checkbox status={'checked'} />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Key" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Key${pair.id+1}`, itemValue)}
                                />        
                            )}
                        name={`Key${pair.id+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Value" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Value${pair.id+1}`, itemValue)}
                                />
                            )}
                        name={`Value${pair.id+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <Controller
                            control={control}
                            render={({field : {value}}) => (
                                <TextInput 
                                    placeholder="Description" 
                                    style={{outline: "none"}}
                                    onChangeText={ (itemValue) => setValue(`Description${pair.id+1}`, itemValue)}
                                />
                            )}
                        name={`Description${pair.id+1}`}
                        defaultValue=""
                        />
                    </DataTable.Cell>
                    <DataTable.Cell>
                        <TouchableOpacity onPress = {() => deleteHandler(pair.id)}>
                            <FontAwesomeIcon icon={faBackspace} size={20} style={[KeyPairRowStyle.iconStyle]}/>
                        </TouchableOpacity>
                    </DataTable.Cell>
                </DataTable.Row>
                    )})}
            </DataTable>
        </View>
    )
}

const KeyPairRowStyle = StyleSheet.create({
    iconStyle: {
        // paddingRight: 10,
        // paddingLeft: 10,
        color: "#dc3545",
    }
})

const KeyPairStyle = StyleSheet.create({
    KeyPairContainer: {
        
    },
    iconStyle: {
        // paddingRight: 10,
        // paddingLeft: 10,
        padding: 20,
        color: "#6c757d",
    },
    textStyle: {
        fontSize: 16,
        fontWeight: "600",
        padding: 20,
        paddingLeft: 60
    },
    KeyPairHeader: {
        // width: 1124,
        flexDirection: "row",
        flex: 1,
        justifyContent: "space-between"
    },
    cellStyle: {

    },
    textInput: {
    }
})

export default KeyPair

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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