React Hook 在单击 2 个不同的按钮时从 APi 获取数据

Posted

技术标签:

【中文标题】React Hook 在单击 2 个不同的按钮时从 APi 获取数据【英文标题】:React Hook to fetch data from APi when click 2 different button 【发布时间】:2021-04-22 20:25:35 【问题描述】:

我已经使用 mongoDB 作为数据库创建了 next.js 应用程序。

所以,我目前有 2 个按钮。 (删除,保存)。我希望我的应用程序在单击“删除”按钮时,它将使用fetch 使用 APi 从 mongoDB 中删除数据。其他,点击“保存”按钮,使用fetch也可以使用API​​将数据保存到mongoDB。

首先,我使用document.getElementById('buttons').addEventListener('click', function (evt)) 获取代码以将代码的字母部分执行到我想要的位置。

然后我使用 if-else 条件根据按钮的 id 在每个按钮上使用不同的 fetch

但是,每次我点击“保存”按钮时,它都会收到警报响应表单浏览器点击“确定”直到我之前点击保存的时间。例如,我点击“保存”按钮,输入数据为product_name = car 和code = 123,之后警报出现,我只需要点击一次“确定”。然后,我点击“保存”按钮,输入数据为product_name = car 和code = 124,之后出现警报,我必须点击两次“确定”。

“删除”按钮也是如此。

我该怎么办?

我在 react 应用的实际页面上的代码。

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

我的 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】:

您会触发多个警报,因为您在每次提交操作发生时(单击“保存”或“删除”时)添加一个事件侦听器。

要解决此问题,只需对代码进行最少的更改,您可以通过删除 addEventListener 并检查提交者 ID 来简单地更新 onSubmit 函数。

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
    
;

【讨论】:

“e”又是从哪里来的?如果“提交者”未定义?我需要导入任何东西吗? @faijiuy 抱歉,忘记添加那部分了。这是回调函数中的第二个参数:(data, e) =&gt; 。我已经更新了我的答案。 至于submitterundefined,这绝不应该发生,因为您必须有一个“提交者”才能触发提交操作。不过,如果你愿意,你可以防范它。

以上是关于React Hook 在单击 2 个不同的按钮时从 APi 获取数据的主要内容,如果未能解决你的问题,请参考以下文章

尝试在单击按钮时从两个不同的文本区域复制文本

按钮单击时从1活动移动到特定片段。

如何在 React Native 中单击按钮时调用具有不同参数的相同 api

如何在离子 3 中单击设备后退按钮时从选项卡 2 导航到选项卡 1

单击按钮时从 Access 数据库中删除特定记录

使用 jQuery 单击时从作为数组的按钮 ID 获取键