React Form with Table

How I can make it so that what is entered in the form is only the initial state of a new row added. And then when the user goes into the cells of the table below, whatever he types into the cell will update the state. Now the way its working if you want to update a row you need to go into the form on the top make your changes and then click the update button on the row you want to update, but this is not the desired behavior. I want the user to make his updates directly into the cells and not need to touch the form on top (only deal with the form on top if he wants to add a new row). I dont care about needing to refresh the page to see changes or the other errors in the console at the moment.

import React from 'react';

import { db } from '../firebase';

class AddunitForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            nameInput: '',
            sizeInput: '',
            priceInput: '',
            submit: '',
            units: [
            ]
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.onDelete = this.onDelete.bind(this)
    }

    componentDidMount() {
        db.collection('locations').get().then((snapshot) => {
            var newUnits = snapshot.docs.map(item => ({
                id: item.id,
                data: item.data()
            }));
            this.setState({ units: newUnits })
        });
    }

    handleChange(event) {
        this.setState({
            input: event.target.value
        });
    }


    handleSubmit(event) {
        event.preventDefault()
        let data = { name: this.state.nameInput, size: this.state.sizeInput, price: this.state.priceInput }
        if(!data.name.trim()||!data.size.trim()||!data.price.trim()){
            window.alert('one or more empty fields, fields cannot be blank')
        } else {
            db.collection('locations').add(data).then((snapshot) => {
                let id = snapshot.id;
                this.setState(prevState => ({
                    units: prevState.units.concat({ data: data, id: id })
                }));
            })
        }
    }


    onDelete = (id) => {
        db.collection('locations').doc(id).delete().then(() => {
            this.setState({
                units: this.state.units.filter((unit) => unit.id !== id)
            });
        })
    }

    onUpdate = (id) => {
        db.collection('locations').doc(id).set({name:this.state.nameInput, size: this.state.sizeInput, price: this.state.priceInput })
    }

    render() {
        return (
            <div>
                <form onSubmit={this.handleSubmit}>
                    Name: 
                    <input value={this.state.nameInput} onChange={(e) => { this.setState({ nameInput: e.target.value }) }} />
                    <br/>
                    Size:
                    <input value={this.state.sizeInput} onChange={(e) => { this.setState({ sizeInput: e.target.value }) }} />
                    <br/>
                    Price: 
                    <input value={this.state.priceInput} onChange={(e) => { this.setState({ priceInput: e.target.value }) }} />
                    <br/>
                    <button type='submit'>Submit!</button>
                </form>
                <table>
                    <thead>
                        <tr>
                            <td>Name</td>
                            <td>Size Sqft</td>
                            <td>Price $</td>
                        </tr>
                    </thead>
                    <tbody>
                        {/* For every unit in this.state.units */}
                        {this.state.units.map((unit) => {
                            return (
                                <tr key={unit.id}>
                                    <td ><input defaultValue={unit.data.name} /></td>
                                    <td ><input defaultValue={unit.data.size}/></td>
                                    <td ><input defaultValue={unit.data.price}/></td>
                                    <button onClick={() => this.onDelete(unit.id)}>Delete</button>
                                    <button onClick={() => this.onUpdate(unit.id)}>Update</button>

                                    

                                </tr>
                            )
                        })}
                    </tbody>
                </table>
            </div>
        );
    }
};


export default AddunitForm;

From point of UX, you don’t want to create 2 different sources of input, so I would remove input form whatsoever and only leave table, in which each cell is editable and your initial state then will be empty table. This is bit advance, but doable :slight_smile:

The problem with this case that you will need custom logic to submit changes to firebase, for example only if all cells in a row have value and some timeout has passed. You can have a look at debounce() function from rxjs library.

Good luck :+1:

I hear what you say but disagree or it doesnt make sense to me, how are you gonna know ahead of time how many rows the user is gonna want to put in his table?

The idea I had is to make that input form on top have the job of adding a new row and setting the initial state for that row. and then the user can edit that row by clicking inside the table and making his edits there directly into the cell of the row he created with the form above. why is that bad?

it is working ok now, I had someone help me a little bit with it. Now what I want to do is that each table will belong to a specific building. for right now the system is setup so that the buildings are already known in advance, the user will not enter in the buildings, but he is responsible for maintaining the tables that belong to each building. so each table will represent all the availabilities of a particular building. If i make a dropdown menu at the top the user would select a particular building, and the corresponding table of availabilities of the building he selected would show up. the job of the input form on top would be to only add available units to the particular table that is selected from the dropdown. So how can the program know which units belong to which building? something like a foreign key in a relational database. how would I go about doing it?
here it is: