1

I'm building a TODO list and one of the things that it needs to do is delete. Here is my server.js code

const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const cpdRoutes = express.Router();
const PORT = 4000;

let Cpd = require("./cpd.model");

app.use(cors());
app.use(bodyParser.json());

//connects my backend to my mongo database
mongoose.connect('mongodb://127.0.0.1:27017/cpds', { useNewUrlParser: true });
const connection = mongoose.connection;

connection.once('open', function() {
    console.log("MongoDB database connection established successfully");
})

cpdRoutes.route('/').get(function(req, res) {
    Cpd.find(function(err, cpds) {
        if (err) {
            console.log(err);
        }
        else {
            res.json(cpds);
        }
    });
});

//finds the data by id
cpdRoutes.route('/:id').get(function(req, res) {
    let id = req.params.id;
    Cpd.findById(id, function(err, cpd) {
        res.json(cpd);
    });
});

//creating data
cpdRoutes.route('/add').post(function(req, res) {
    let cpd = new Cpd(req.body);
    cpd.save()
        .then(cpd => {
            res.status(200).json({'cpd': 'New data added successfully'});
        })
        .catch(err => {
            res.status(400).send('Adding new data failed');
        });
});

//update data
cpdRoutes.route('/update/:id').post(function(req, res) {
    Cpd.findById(req.params.id, function(err, cpd) {
        if (!cpd)
            res.status(404).send("data is not found");
        else
            cpd.cpd_date = req.body.cpd_date;
            cpd.cpd_activity = req.body.cpd_activity;
            cpd.cpd_hours = req.body.cpd_hours;
            cpd.cpd_learningStatement = req.body.cpd_learningStatement;

            cpd.save().then(cpd => {
                res.json('Data updated!');
            })
            .catch(err => {
                res.status(400).send("Update not possible");
            });
    });
});

// cpdRoutes.route('/delete/:id').post(function(req, res) {
//     Cpd.findById(req.params.id, function(err, cpd) {
//         if (!cpd)
//             res.status(404).send("data is not found");
//         else
//             cpd.cpd_date = req.body.cpd_date;
//             cpd.cpd_activity = req.body.cpd_activity;
//             cpd.cpd_hours = req.body.cpd_hours;
//             cpd.cpd_learningStatement = req.body.cpd_learningStatement;

//             cpd.save().then(cpd => {
//                 res.json('Data updated!');
//             })
//             .catch(err => {
//                 res.status(400).send("Update not possible");
//             });
//     });
// });

cpdRoutes.route.get('/delete', function(req, res){
    var id = req.query.id;
    Cpd.find({_id: id}).remove().exec(function(err, expense) {
     if(err)
      res.send(err)
     res.send('Data successfully deleted!');
    })
});

app.use('/cpds', cpdRoutes);

app.listen(PORT, function() {
    console.log("Server is running on Port: " + PORT);
});

My delete component:

import React from 'react';
import axios from 'axios';
import { Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';


class DeleteCpd extends React.Component {
    constructor(){
        super();
            this.state={id:''};
            this.onClick = this.onClick.bind(this);
            this.delete = this.delete.bind(this);
    }

    // componentDidMount() {
    //     this.setState({
    //     id: this.props.cpds.id
    //     })
    // }
    componentDidMount() {
        axios.get('http://localhost:4000/cpds/'+this.props.match.params.id)
            .then(response => {
                this.setState({
                    cpd_date: response.data.cpd_date,
                    cpd_activity: response.data.cpd_activity,
                    cpd_hours: response.data.cpd_hours,
                    cpd_learningStatement: response.data.cpd_learningStatement
                })   
            })
            .catch(function (error) {
                console.log(error);
            })
    }

    onClick(e){
        this.delete(this);
    }

    delete(e){
        axios.get('http://localhost:4000/cpds/'+this.props.match.params.id)
        .then(function(response) {

        });
    }

    render(){
    return (
        <Button onClick={this.onClick}>
            <Link to={{pathname: '/', search: '' }} style={{ textDecoration: 'none' }}>
                <span className="glyphicon glyphicon-remove"></span>
            </Link>
        </Button>
    )
    }
}

export default DeleteCpd;

and my App.js:

import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

import "bootstrap/dist/css/bootstrap.min.css";

import CreateCpd from "./components/create-cpd.component";
import EditCpd from "./components/edit-cpd.component";
import CpdsList from "./components/cpds-list.component";
import DeleteCpd from "./components/cpds-delete.component";

class App extends Component {
  render() {
    return (
      <Router>
        <div className="container">
          <nav className="navbar navbar-expand-lg navbar-light bg-light">
            <Link to="/" className="navbar-brand">MERN-Stack Cpd tracker App</Link>
            <div className="collpase navbar-collapse">
              <ul className="navbar-nav mr-auto">
                <li className="navbar-item">
                  <Link to="/" className="nav-link">Data List</Link>
                </li>
                <li className="navbar-item">
                  <Link to="/create" className="nav-link">Create Cpd data</Link>
                </li>
              </ul>
            </div>
          </nav>
          <br/>
          <Route path="/" exact component={CpdsList} />
          <Route path="/edit/:id" component={EditCpd} />
          <Route path="/delete/:id" component={DeleteCpd} />
          <Route path="/create" component={CreateCpd} />
        </div>
      </Router>
    );
  }
}

export default App;

This is the error my getting:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in CpdList (created by Context.Consumer)

What I'm trying to do is delete via id. What am I doing wrong?

This is my CPDList:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
// import { CSVLink } from "react-csv";
// import DeleteCpd from './cpd_delete.component';

const Cpd = props => (
    <tr>
        <td>{props.cpd.cpd_date}</td>
        <td>{props.cpd.cpd_activity}</td>
        <td>{props.cpd.cpd_hours}</td>
        <td>{props.cpd.cpd_learningStatement}</td>
        <td>{props.cpd.cpd_evidence}</td>
        <td>
            <Link to={"/edit/"+props.cpd._id}>Edit</Link>
        </td>
        <td>
            <Link to={"/delete/"+props.cpd._id}>Delete(not working yet)</Link>
        </td>
    </tr>
)


export default class CpdList extends Component {

    constructor(props) {
        super(props);
        this.state = {
            cpds: [],
            // csvData:[
            //     {
            //         "date": ""
            //     },
            //     {
            //         "activity": ""
            //     },
            //     {
            //     "hours": ""
            //     },
            //     {
            //     "learningStatement": ""
            //     },
            //     {
            //         "evidence": ""
            //     }
            // ]
        };
    };

    // exportCsv()
    // {
    //     var csvRow=[];
    // }


    componentDidMount() {
        axios.get('http://localhost:4000/cpds/')
            .then(response => {
                this.setState({ cpds: response.data });
            })
            .catch(function (error){
                console.log(error);
        });
    };

    componentDidUpdate() {
        axios.get('http://localhost:4000/cpds/')
        .then(response => {
            this.setState({ cpds: response.data });
        })
        .catch(function (error){
            console.log(error);
    });
    }

    cpdList() {
        return this.state.cpds.map(function(currentCpd, i){
            return <Cpd cpd={currentCpd} key={i} />;
        });
    }

    render() {
        return(
            <div>
                <h3>Cpd Data List</h3>
                    <table className="table table-striped" style={{ marginTop: 20 }} >
                        <thead>
                            <tr>
                                <th>Date</th>
                                <th>Activity</th>
                                <th>Hours</th>
                                <th>Learning Statement</th>
                                <th>Evidence</th>
                            </tr>
                        </thead>
                    <tbody>
                        { this.cpdList() }
                    </tbody>
                </table>

                {/* <CSVLink data={csvData}
                    filename={"db.csv"}
                    color="primary"
                    style={{float: "left", marginRight: "10px"}}
                    className="btn btn-primary"
                        >Download .CSV
                </CSVLink> */}

            </div>
        )
    }
};

please ignore the commented out code still working on that.

  • Just an observation but your passing "this" to this.delete() in your onClick function instead of passing along e. – Mike Nov 25 '19 at 13:23
  • Based on the error isn't the problem CpdList component? could you paste the CpdList Component here also? – Itay Wolfish Nov 25 '19 at 14:51
  • @ItayWolfish i pasted my Cpdlist, what do you think the problem could be? – Sean van Loggerenberg Nov 26 '19 at 06:04
  • Okay, this is very common mistake. You are trying to update the state of unmounted component. one way to fix is to have a variable which checks whether component is mounted or not, if it's true then perform setState. In constructor set `this.isMounted` to false, and in componentDidMount set `this.isMounted` to `true` and finally in `componentWillUnMount` set it to false. – Gulam Hussain Nov 26 '19 at 06:11
  • @hussain.codes sorry to ask but in what component should i input this.isMounted? – Sean van Loggerenberg Nov 26 '19 at 06:26
  • are you updating state in your delete function, in `< DeleteCpd/>` component? – Gulam Hussain Nov 26 '19 at 06:42
  • to be honest im so confused right now @hussain.codes – Sean van Loggerenberg Nov 26 '19 at 06:52
  • This might not solve actual problem, but in your `` component. You are performing two action by clicking on `` component. First is calling invoking delete function and second is redirecting to `/`. try not to do both at once. remove `` component from `` component. and in delete function after making api call redirect your user to `/` (for redirecting, check this https://stackoverflow.com/questions/43230194/how-to-use-redirect-in-the-new-react-router-dom-of-reactjs). – Gulam Hussain Nov 26 '19 at 06:57

0 Answers0