Jeyanth Kanagaraj
Jeyanth Kanagaraj

Reputation: 271

Updating the added data using the same form | Reactjs

Here, I am trying to do an CRUD process. Now, I can add, delete and display data. But, i couldn't update the existing data. I want to update or edit the existing data. I tried different methods, to achieve that, but none works. Please check my code below and let me know, how can i make that.

App Component:

import React, { Component } from 'react';
import { withStyles, Grid } from '@material-ui/core';
import styles from './Style'
import Form from './Form';
import DataList from './DataList';
import Header from '../../components/Header';

class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            Datas: [
                {id: 0, Name: 'Tony Stark', Occupation: 'Iron Man', Details: 'SuperHero, PlayBoy, Philatherophist' },
                {id: 1, Name: 'Steve Rogers', Occupation: 'Captain America', Details: 'Captain, Soldier, SuperHero' },
                {id: 2, Name: 'Thor', Occupation: 'God of Thunder', Details: 'SuperHero, God, King' },
            ],
            Name: "",
            Occupation: "",
            Details: "",
        }
    }

    handleChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value       
         })
    }

    handleClick = (e, data) => {
        e.preventDefault();
        //data.id = Math.random()
        let Datas = [...this.state.Datas, {id: Math.random(), Name: this.state.Name, Occupation: this.state.Occupation, Details: this.state.Details}];
        this.setState({
            Datas
        })
        this.reset()
    }

    handleDelete = (id) => {
        const Datas = this.state.Datas.filter(data=>{
            return data.id !== id
        });
        this.setState({
            Datas
        })
    };

    handleUpdate = (e, id) => {

        const index = this.state.Datas.findIndex((data)=>{
            return data.id === id
        });

        const data = Object.assign({}, this.state.Datas[index])
        data.Name = e.target.value
        data.Occupation = e.target.value
        data.Details = e.target.value

        const Datas = Object.assign([], this.state.Datas);
        Datas[index]= data;
        this.setState({
            Datas
        })
    }

    reset = () => {
        this.setState({
           Name: "",
           Occupation: "",
           Details: ""
        })
    }
    render() {
        const { classes } = this.props
        const { Name, Occupation, Details, Datas } = this.state
        return (
            <div>
                <Header />
                <Grid container >
                    <Grid item xs = {6}>
                        <div className={classes.cover}>
                            <Form 
                                handleChange={this.handleChange} 
                                handleClick={this.handleClick} 
                                Name={Name} 
                                Occupation={Occupation} 
                                Details={Details} 
                            />
                        </div>
                    </Grid>
                    <Grid item xs = {6}>
                        <div className={classes.cover}>
                            <DataList 
                                datas={Datas}
                                handleDelete={this.handleDelete}
                                handleUpdate={this.handleUpdate}
                            />
                        </div>
                    </Grid>
                </Grid>

            </div>
        )
    }
}

export default withStyles(styles)(App)

Form Component

import React from 'react';
import { withStyles, TextField, Button } from '@material-ui/core';
import styles from './Style'


const Form = (props) => {
    const { classes, Name, Occupation, Details } = props
    return (
        <div>
            <form >
                <TextField
                    type="text"
                    name="Name"
                    label="Name"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Name}
                />
                <TextField
                    type="text"
                    name="Occupation"
                    label="Occupation"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Occupation}
                />
                <TextField
                    type="text"
                    name="Details"
                    label="Details"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Details}
                />
                <Button variant="outlined" onClick={props.handleClick} type="submit" className = {classes.button}>Submit</Button>
            </form>
        </div>
    )
}

export default withStyles(styles)(Form)

DataList Component

import React from 'react';
import { withStyles, Card, CardContent, Typography, IconButton} from '@material-ui/core';
import Delete from '@material-ui/icons/DeleteOutlined'
import styles from './Style'

const DataList = (props) => {
    const { datas, classes } = props
    return (
        <div>
            {
            datas.map((data)=> {
                return (
                    <Card key={data.id} className={classes.card} onClick={(e) => props.handleUpdate(e, data.id)} elevation={1}>
                        <CardContent>
                            <IconButton aria-label="Delete" className={classes.delete} onClick={()=>props.handleDelete(data.id)}>
                                <Delete />
                            </IconButton>
                            <Typography variant="h4" className={classes.name}>
                                {data.Name}
                            </Typography>
                            <Typography variant="h6" className={classes.body}> 
                                {data.Occupation}
                            </Typography>
                            <Typography variant="body1" className={classes.details}>
                                {data.Details}
                            </Typography>
                        </CardContent>
                    </Card>
                )
            })
            }
        </div>
    )
}

export default withStyles(styles)(DataList)

Upvotes: 2

Views: 1770

Answers (1)

Hemant Parashar
Hemant Parashar

Reputation: 3774

It should be id and then event ( swap the arguments ). You're expecting a bound function to receive the event as the first argument, whereas it will be the id. Also, you don't need to bind the function to this(BTW which will be undefined) since you defined handleupdate as an arrow function in App.

 handleUpdate = (id, event) => {
   .
   .
   .        
 }

OR

you can just simply do

<Card key={data.id} className={classes.card} 
      onClick={ e => { 
        props.handleUpdate(e, data.id) 
      }} 
      elevation={1}
>

------------ Updated -----------

Here is the Solution -

You can use Id in your state to track which object is being currently edited and Editing to track that the form is in editing state for updation. Editing state is then used to render a save button for edtis rather than a submit.

App.js

import React, { Component } from "react";
import { withStyles, Grid } from "@material-ui/core";
import styles from "./Style";
import Form from "./Form";
import DataList from "./DataList";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            Datas: [
                {
                    id: 0,
                    Name: "Tony Stark",
                    Occupation: "Iron Man",
                    Details: "SuperHero, PlayBoy, Philatherophist"
                },
                {
                    id: 1,
                    Name: "Steve Rogers",
                    Occupation: "Captain America",
                    Details: "Captain, Soldier, SuperHero"
                },
                {
                    id: 2,
                    Name: "Thor",
                    Occupation: "God of Thunder",
                    Details: "SuperHero, God, King"
                }
            ],
            Id: "",
            Name: "",
            Occupation: "",
            Details: "",
            IsEditing: false
        };
    }

    handleChange = e => {
        this.setState({
            [e.target.name]: e.target.value
        });
    };

    handleClick = (e, data) => {
        e.preventDefault();
        //data.id = Math.random()
        let Datas = [
            ...this.state.Datas,
            {
                id: Math.random(),
                Name: this.state.Name,
                Occupation: this.state.Occupation,
                Details: this.state.Details
            }
        ];
        this.setState({
            Datas
        });
        this.reset();
    };

    handleDelete = id => {
        const Datas = this.state.Datas.filter(data => {
            return data.id !== id;
        });
        this.setState({
            Datas
        });
    };

    handleUpdate = (e, id) => {
        const index = this.state.Datas.findIndex(data => {
            return data.id === id;
        });

        const data = Object.assign({}, this.state.Datas[index]);
        this.setState({
            Id: data.id,
            Name: data.Name,
            Occupation: data.Occupation,
            Details: data.Details,
            IsEditing: true
        });
    };

    saveUpdate = id => {
        const newData = this.state.Datas.map(d => {
            console.log(id, d.id);
            if (d.id === id) {
                return {
                    Name: this.state.Name,
                    Occupation: this.state.Occupation,
                    Details: this.state.Details
                };
            }
            return d;
        });

        this.setState(
            {
                Datas: newData,
                IsEditing: false
            },
            () => {
                this.reset();
            }
        );
    };

    reset = () => {
        this.setState({
            Id: "",
            Name: "",
            Occupation: "",
            Details: ""
        });
    };
    render() {
        const { classes } = this.props;
        const { Id, Name, Occupation, Details, Datas, IsEditing } = this.state;
        return (
            <div>
                <Grid container>
                    <Grid item xs={6}>
                        <div className={classes.cover}>
                            <Form
                                handleChange={this.handleChange}
                                handleClick={this.handleClick}
                                saveUpdate={this.saveUpdate}
                                Id={Id}
                                Name={Name}
                                Occupation={Occupation}
                                Details={Details}
                                Editing={IsEditing}
                            />
                        </div>
                    </Grid>
                    <Grid item xs={6}>
                        <div className={classes.cover}>
                            <DataList
                                datas={Datas}
                                handleDelete={this.handleDelete}
                                handleUpdate={this.handleUpdate}
                            />
                        </div>
                    </Grid>
                </Grid>
            </div>
        );
    }
}

export default withStyles(styles)(App);

Form.js

import React from "react";
import { withStyles, TextField, Button } from "@material-ui/core";
import styles from "./Style";

const Form = props => {
    const { Id, classes, Name, Occupation, Details, Editing } = props;
    return (
        <div>
            <form>
                <TextField
                    type="text"
                    name="Name"
                    label="Name"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Name}
                />
                <TextField
                    type="text"
                    name="Occupation"
                    label="Occupation"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Occupation}
                />
                <TextField
                    type="text"
                    name="Details"
                    label="Details"
                    className={classes.textField}
                    onChange={props.handleChange}
                    value={Details}
                />
                {Editing ? (
                    <Button
                        variant="outlined"
                        onClick={e => {
                            e.preventDefault();
                            props.saveUpdate(Id);
                        }}
                        type="button"
                        className={classes.button}
                    >
                        Update
                    </Button>
                ) : (
                    <Button
                        variant="outlined"
                        onClick={props.handleClick}
                        type="submit"
                        className={classes.button}
                    >
                        Submit
                    </Button>
                )}
            </form>
        </div>
    );
};

export default withStyles(styles)(Form);

Upvotes: 1

Related Questions