尝试使用空输入字段提交时,React 应用程序崩溃

Posted

技术标签:

【中文标题】尝试使用空输入字段提交时,React 应用程序崩溃【英文标题】:React app crashed when trying to submit with empty input field 【发布时间】:2022-01-20 11:01:30 【问题描述】:

请帮我解决这个问题,因为我搜索了所有互联网但找不到答案:(

我正在使用 MERN Stack 制作网站,但遇到了一个问题:

每当我点击空输入字段上的更新时,我的应用就会崩溃。

当我在 Axios 更新请求中发现错误时,它只是说 Network Error

我想问一下有没有办法解决这个错误? 也许如果输入字段为空,更新按钮不会触发?

这是我的代码:

// DinnerIdeas.js
import React,  useState, useEffect  from "react"
import './DinnerIdeas.css'
import Axios from "axios"

import FoodListComponent from "../FoodListComponent";
import FormComponent from "../FormComponent";

function DinnerIdeas() 

    const [foodName, setFoodName] = useState('')
    const [isVegetarian, setVegetarian] = useState(false)
    const [priceRange, setPriceRange] = useState('$')
    const [newFoodName, setNewFoodName] = useState(null)
    const [foodList, setFoodList] = useState([])
  
    // Read:
    useEffect(() => 
      let unmounted = false
      Axios.get("http://localhost:3001/read")
      .then((response) => 
        if (!unmounted) 
          setFoodList(response.data)
        
      )
      .catch(error => 
        console.log(`Hey, the error is $error`)
        return
      )
      return () => 
        unmounted = true
      
    , [foodList])
  
    // Create:
    const addToList = () => 
      Axios.post(
        "http://localhost:3001/insert", 
        
          foodName: foodName,
          isVegetarian: isVegetarian,
          priceRange: priceRange,
        
      )
    
  
    // Update:
    const updateFood = (id) => 
      Axios.put("http://localhost:3001/update", 
        id: id,
        newFoodName: newFoodName,
      )
      .catch(error => console.log(`Hey, the error is $error`))
    
  
    // Delete:
    const deleteFood = (id) => 
      Axios.delete(`http://localhost:3001/delete/$id`)
    
    
    return (
      <section className="dinner-ideas">
        <FormComponent
          setFoodName=setFoodName
          setVegetarian=setVegetarian
          setPriceRange=setPriceRange
          addToList=addToList
        />
        <FoodListComponent 
          foodList=foodList 
          setNewFoodName=setNewFoodName
          updateFood=updateFood 
          deleteFood=deleteFood
        />
      </section>
    );
  
  
  export default DinnerIdeas;

表单组件:

export default function FormComponent(props) 
    return (
        <div className="dinner container">
            <h1 className="dinner--title">Dinner Ideas</h1>
            <form>
                <div className="form-group">
                    <label htmlFor="name">Food name:</label>
                    <input
                        type="text"
                        name="name"
                        placeholder="Ex: Pesto Pasta"
                        maxLength="50"
                        onChange=(event) => props.setFoodName(event.target.value)
                        required
                    />
                </div>
                <br />
                <div className="form-group">
                    <label htmlFor="vegetarian"> Is this dish Vegetarian?</label>
                    <select
                        name="vegetarian"
                        onChange=(event) => props.setVegetarian(event.target.value)
                    >
                        <option value="false">No</option>
                        <option value="true">Yes</option>
                    </select>
                </div>
                <br />
                <div className="form-group">
                    <label htmlFor="price">Price range:</label>
                    <select
                        name="price"
                        onChange=(event) => props.setPriceRange(event.target.value)
                    >
                        <option value="$">$</option>
                        <option value="$$">$$</option>
                        <option value="$$$">$$$</option>
                    </select>
                </div>
                <br />
            </form>
                <button 
                    type="submit"
                    className="dinner--btn" 
                    onClick=props.addToList
                >
                    Add to list
                </button>
        </div>
    )

服务器端:index.js

const express = require("express") // Set up an express server
const mongoose = require("mongoose") // Import Mongoose library
const cors = require('cors') // Import CORS to communicate with frontend
const app = express() // Initializing our express server

const DinnerModel = require('./models/Dinner')

app.use(express.json()) // Setting up Middleware
app.use(cors())

// Connect to MongoDB
mongoose.connect(
    'mongodb+srv://higherstates:<password>@crud.cvewg.mongodb.net/dinner_ideas?retryWrites=true&w=majority', 
    
        useNewUrlParser: true,
    
)

// Create:
app.post("/insert", async (req, res) => 
    const foodName = req.body.foodName
    const isVegetarian = req.body.isVegetarian
    const priceRange = req.body.priceRange

    const dinner = new DinnerModel(
         
            foodName: foodName, 
            isVegetarian: isVegetarian,
            priceRange: priceRange,
        
    )

    try 
        await dinner.save()
        res.send("data inserted")
     catch(err) 
        console.log(err)
    
)

// Read:
app.get("/read", async (req, res) => 
    DinnerModel.find(, (err, result) => 
        if (err) 
            res.send(err)
        
        res.send(result)
    )
)

// Update:
app.put("/update", async (req, res) => 
    const newFoodName = req.body.newFoodName
    const id = req.body.id

    try 
        await DinnerModel.findById(id, (err, updatedFood) => 
            updatedFood.foodName = newFoodName
            updatedFood.save()
            res.send("update")
        ).clone()
     catch(err) 
        console.log("The error is: " + err)
    
)


app.delete("/delete/:id", async (req, res) => 
    const id = req.params.id

    await DinnerModel.findByIdAndRemove(id).exec()
    res.send("deleted")
)

// Creating a port:
app.listen(3001, () => 
    console.log("Server is up on: http://localhost:3001")
)

食物列表组件:

export default function FoodListComponent(props) 
return (
    <div className="food-list container">
        <h1 className="food-list--title">Food List</h1>
        <table>
        <thead>
            <tr>
                <th className="th--name">Name</th>
                <th className="th--vegetarian">Vegetarian</th>
                <th className="th--price">Price</th>
                <th className="th--edit">Edit</th>
                <th className="th--actions">Action</th>
            </tr>
        </thead>
        <tbody>
            props.foodList.length > 0 && props.foodList.map((val, key) => 
                return (
                    <tr key=key>
                        <td>val.foodName</td>
                        <td>
                            val.isVegetarian ? <input type="checkbox" checked readOnly /> : <input type="checkbox" disabled="disabled" readOnly  />
                        </td>
                        <td>val.priceRange</td>
                        <td>
                        <input
                            name="edit"
                            placeholder="New food name.."
                            size="15"
                            maxLength="50"
                            onChange=(event) => props.setNewFoodName(event.target.value)
                        >
                        </input>
                        </td>
                        <td>
                            <button
                                className="table--btn"
                                onClick=() => props.updateFood(val._id)
                            >
                                Update
                            </button>
                            <button 
                                className="table--btn"
                                onClick=() => props.deleteFood(val._id)
                            >
                                ❌
                            </button>
                        </td>
                    </tr>
                )
            )
        </tbody>
        </table>
    </div>
  )

Mongoose 架构:

    const mongoose = require('mongoose')
    
    const DinnerSchema = new mongoose.Schema(
        foodName: 
            type: String,
            default: true,
        ,
        isVegetarian: 
            type: Boolean,
            required: true,
        ,
        priceRange: 
            type: String,
            required: true,
        
    )

const Dinner = mongoose.model("Dinner", DinnerSchema)
module.exports = Dinner

演示如下:

1. 如果我在没有填写**Edit field**的情况下点击**Update button**,它不会做任何事情,但是当我刷新页面时数据会消失。 控制台中的错误消息:

https://i.stack.imgur.com/cyAtQ.gif [演示gif]

    应用程序崩溃,这是服务器终端中的错误消息

https://i.stack.imgur.com/bgayZ.jpg [nodemon 应用崩溃错误]

谢谢大家!

【问题讨论】:

您是否尝试修复 CORS 错误,因为您可能向其他域发送请求而不是您的 react 应用程序? 我认为错误很明显。在 mongo 模式中,名称是 required 并且您发送的是一个空值。如果您打算允许空值,请修改架构以允许它。或使用客户端验证阻止 API 调用在值为空时发生 似乎 foodName 是必需的,并且您没有对 foorName 进行任何空值检查 @programoholic 我将架构从required: true 更改为default: undefined。现在更新按钮将不再提交空值,而是上面的 FormComponent,当我单击“添加到列表”时,它会将空值输入到数据库中。有什么办法可以解决这个问题? @RamRana 嗨,我们应该把空检查放在哪里?你能告诉我更多关于这方面的信息吗?谢谢:) 【参考方案1】:
 // Update:
    const updateFood = (id) => 
if(newFoodName)
      Axios.put("http://localhost:3001/update", 
        id: id,
        newFoodName: newFoodName,
      )
      .catch(error => console.log(`Hey, the error is $error`))
    

【讨论】:

以上是关于尝试使用空输入字段提交时,React 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

欧芹为空字段触发错误

在 React 中提交表单时如何获取要显示的名称和 uuid

表单输入的值在 React 中提交时未更新

用ant-design在react js中提交后清除表单输入字段值

在React Form无状态组件和状态完全Root组件之间传递多个输入字段

React fetch post 请求中的空属性和值