2

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)

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

6 Comments

I changed the code as you mentioned. But, still getting the same error "TypeError: Cannot read property 'value' of undefined". I have also updated the code above
Hi @HemantParashar, Here is the CodeSandBox link codesandbox.io/s/black-river-70h93
If you log e.target you'll see that it's a button and not an input...which does'nt have a value. What are you expecting e.target.value to be? I don't understand the data.Name = e.target.value; data.Occupation = e.target.value; data.Details = e.target.value;
Don't worry about my update function code, its not perfect. All i want to do is onClicking the edit logo button, the data should display on the textfields and it can be able to edit and update again
@JeyanthKanagaraj Okay got it. Updated the answer for what you needed to do. Added modifications in App.js and Form.js
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.