React Hook to fetch data from APi when click 2 different button

Viewed 423

I have create next.js app with using mongoDB as database.

So, I currently have 2 buttons. (Delete, Save). I want my application to when click 'Delete' button, it will then use fetch to delete data from mongoDB using APi. Other, click 'Save' button, use fetchto save data to mongoDB using APi as well.

First, I use document.getElementById('buttons').addEventListener('click', function (evt)) to get to the code to do the letter part of code to where I want.

Then I use the if-else condition to use different fetch on each button based on buttons' id.

But, every time I click 'save' button, it will get alert respond form browser to click 'ok' up to the time that I click save before. For example, I have click 'save' button with input data of product_name = car and code = 123 after that the alert show up and I have to only click 'ok' one time. Then later, I click 'save' button with input data of product_name = car and code = 124 after that the alert show up and I have to click 'ok' Two time.

The same go for 'Delete' button as well.

What should I do?

My code on actual page on react app.

import Head from 'next/head'
import styles from '../styles/Home.module.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import ButtonBar from '../components/buttonBar'
import InputGroup from 'react-bootstrap/InputGroup'
import FormControl from 'react-bootstrap/FormControl'
import BrandList from '../components/brandList'
import ModelList from '../components/modelList'
import Button from 'react-bootstrap/Button'
import ButtonGroup from 'react-bootstrap/ButtonGroup'
import {connectToDatabase} from "../util/mongodb"
import {useForm} from "react-hook-form";

export default function AddItem({item}) {

const {register, handleSubmit, watch, errors} = useForm();
const onSubmit = (data) => {
  console.log(data)


  document.getElementById('buttons').addEventListener('click', function(evt) {
     var target = evt.target;
     if (target.id === 'add_item') {
        fetch('/api/item', {
            method: 'POST', // *GET, POST, PUT, DELETE, etc.
            mode: 'cors', // no-cors, *cors, same-origin
            cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
            credentials: 'same-origin', // include, *same-origin, omit
            headers: {
            'Content-Type': 'application/json'// 'Content-Type': 'application/x-www-form-urlencoded',
        },
            redirect: 'follow', // manual, *follow, error
            referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
            body: JSON.stringify(data) // body data type must match "Content-Type" header
      })
      .then(response => response.json())
      .then(data => {
        console.log(data);
        alert("Response from server " + data.message)
      });
  } else if (target.id === 'del_item') {
    fetch('/api/item', {
        method: 'DELETE', // *GET, POST, PUT, DELETE, etc.
        mode: 'cors', // no-cors, *cors, same-origin
        cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
        credentials: 'same-origin', // include, *same-origin, omit
        headers: {
          'Content-Type': 'application/json'
          // 'Content-Type': 'application/x-www-form-urlencoded',
        },
        redirect: 'follow', // manual, *follow, error
        referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
        body: JSON.stringify(data) // body data type must match "Content-Type" header
      })
      .then(response => response.json())
      .then(data => {
        console.log(data);
        alert("Response from server " + data.message)
      });
  }
}, false);} return (
<form onSubmit = {handleSubmit(onSubmit)}>
<Head >
   <title> Add / Edit </title> <link rel = "icon" href = "/favicon.ico" / >
</Head>
<main className = {styles.main}>
<p className = {styles.title}>Add / Edit `</p>


Product Name: < input type = "text" name = "product_name" ref = {register({required: true})}/><br / >

Product Code: < input type = "text" name = "code"ref = {register}/><br / >

</main>

   <div id = "buttons" >
      <Button variant = "danger" type = "submit" value = "DELETE" id = "del_item"> Delete </Button{' '}
      <Button type = "submit" value = "POST" id = "add_item" > Save < /Button>{' '}
      <Button variant = "dark" > Back < /Button>{' '}
   </div> <
/form>)}

export async function getServerSideProps() { const {db} = await connectToDatabase();
const item = await db
   .collection("item")
   .find({})
   .sort({})
   .limit(20)
   .toArray();

return {
   props: {
      item: JSON.parse(JSON.stringify(item)),
   },
};}

My APi:

import { connectToDatabase } from "../../util/mongodb";

export default async (req, res) => {
   console.log("item API method " + req.method)

   if (req.method === 'GET') {
      const { db } = await connectToDatabase();
      const item = await db
         .collection("item")
         .find({})
         .sort({})
         .limit(20)
        .toArray();
      res.json(balance);
   } else if (req.method === 'POST') {
      console.log("item REQ", req.body)
      let data = req.body;

      let { product_name, code, brand, model, avi_model, purchase_price, amount, limit_amount, barcode_id, date } = data;

      const { db } = await connectToDatabase();
      let doc = await db
         .collection('item')
         .updateOne(
            {
              product_name: product_name,
              code: code,
              brand: brand,
              model: model,
              avi_model: avi_model,
              purchase_price: purchase_price,
              amount: amount,
              limit_amount: limit_amount,
              barcode_id: barcode_id,
              date: date
            },
            { $set: data },
            { upsert: true }
         ) // if update non-existing record, insert instead.

      res.json({ message: 'OK' });
   } else if (req.method === 'DELETE') {
      let data = req.body
      let { product_name } = data;
      const { db } = await connectToDatabase();
      let doc = await db 
         .collection('item')
         .deleteOne({ product_name: product_name})
      res.json({delete: true, message: 'Delete data', data: {}})
   }}
1 Answers

You're getting multiple alerts triggered because you're adding an event listener every time a submit action happens (when clicking on either "Save" or "Delete").

To fix this, with minimal code changes, you could simply update the onSubmit function by removing the addEventListener and checking for the submitter ID instead.

const onSubmit = (data, e) => {
    console.log(data);

    const submitterId = e.nativeEvent.submitter.id;
    if (submitterId === 'add_item') {
        // Your `Add Item` logic here
    } else if (submitterId === 'del_item') {
        // Your `Delete Item` logic here
    }
};
Related