【问题标题】:Change state and update it in the database更改状态并在数据库中更新它
【发布时间】:2021-12-31 05:49:26
【问题描述】:

我正在开发一个使用 React.js、MongoDB、Node.js 和 Express 跟踪水果供应商库存的网络应用程序。我调用了我的数据库端点来呈现表中的数据。现在我尝试使用按钮增加和减少库存量,但是当我尝试设置新状态时,它不起作用。我尝试通过单击更改状态,然后更新数据库中的新状态。有什么建议吗?

  • FruitTable 组件:

    导入 Reac, { 组件 } from 'react'; 从'react-bootstrap'导入*作为ReactBootstrap; 从'axios'导入axios; 从'react-bootstrap/Button'导入按钮;

    类 FruitTable 扩展组件 {

    constructor(props) {
      super(props)
    
      this.state = {
        fruits: []
      }
      this.handleClick = this.handleClick.bind(this)
    }
    
    
    componentDidMount() {
      axios.get('http://localhost:5000/fruits/')
      .then(res => {
        this.setState({
          fruits: res.data
        });
       })
      .catch((error) => {
        console.log(error)
      })
    
    
    
    }
    
    handleClick =  () => {
      const fruits = [...this.state.fruits]
      this.setState({fruits: this.state.fruits[1] +1})
    
      }
    
    
    render() {
    
      return(
        <div>
         <h1>Fruit Vendor Stock</h1>
        <ReactBootstrap.Table striped bordered hover size="sm">
      <thead>
        <tr>
          <th>#</th>
          <th>Name</th>
          <th>Stock</th>
          <th>Price</th>
          <th>Add/Reomve</th>
        </tr>
      </thead>
      <tbody> 
        {
          this.state.fruits.map((fruit, index) => (
            <tr>
            <th scope="row">{index + 1}</th>
            <td>{fruit.name}</td>
            <td>{fruit.stock}</td>
            <td>{fruit.price}</td>
            <td>
              <div className="mb2">
              <Button className="btn btn-primary btn-sm"
                onClick={this.handleClick}
              >Add</Button>{' '}
              <Button className="btn btn-danger btn-sm"
    
              >Remove</Button> 
              </div>
            </td>
            </tr>
            ))
        }
      </tbody>
       </ReactBootstrap.Table>
      </div>
      )
    };
    

    }

    导出默认 FruitTable;

  • FruitsData.model

    const mongoose = require('mongoose');

    const Schema = mongoose.Schema;

    const fruits = new Schema({ 名称:{类型:字符串,必需:真}, 库存:{类型:数字,必填:真}, 价格:{类型:数字,必填:真}, }, {

    });

    const Fruits = mongoose.model('Fruits', fruits);

    module.exports = 水果;

-路线:

const router = require('express').Router();
let Fruit = require('../models/fruit_data');

router.route('/').get((req, res) => {
    Fruit.find()
    .then(fruits => res.json(fruits))
    .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/add').post((req, res) => {
    const name = req.body.name;
    const stock = Number(req.body.stock);
    const price = Number(req.body.price);

    const newFruit = new Fruit({
        name,
        stock,
        price,
    });

    newFruit.save()
    .then(() => res.json('Fruit has been added!'))
    .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/:id').get((req, res) => {
    Fruit.findById(req.params.id)
    .then(Fruit => res.json(Fruit))
    .catch(err => res.status(400).json('Error: ' + err));
});

router.route('/:id').delete((req, res) => {
    Fruit.findByIdAndDelete(req.params.id)
    .then(() => res.json('Fruit has deleted.'))
    .catch(err => res.status(400).json("Error: " + err));
});

router.route('/update/:id').put((req, res, next) => {
    Fruit.findByIdAndUpdate(req.params.id, {
        $set: req.body
    }, (error, data) => {
        if(error) {
            return next(error);
            console.log(error)
        } else {
            res.json(data)
            console.log('Stock has been updated')
        }
    })   
    })

module.exports = 路由器;

-Server.js:

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');

require('dotenv').config();

const app = express();
const port = process.env.PORT || 5000;

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


const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDb database connection established successfully!!")

})

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

const fruitsRouter = require('./routes/fruit');

app.use('/fruits', fruitsRouter);




app.listen(port, () => {
console.log(`Server is running on port: ${port}`);

})

-App.js:

import "./App.css";
import React, { Component, useState, useEffect } from "react";
import FruitTable from "./Components/fruitTable";
import "bootstrap/dist/css/bootstrap.min.css";
import { sendEmail } from "./service/emailService";
import axios from 'axios';

function App() {


  return (
    <div className="App">
     <FruitTable  />
    </div>
   );
  }

导出默认应用;

【问题讨论】:

  • #1 “不起作用”是什么意思?你有什么错误吗? #2 如果您在浏览器控制台端或快速服务器端没有任何错误,请添加多个日志,例如 console.log("before foo")console.log("after click")console.log("on stock increment service") 等,以找到确切的错误行。 #3 您的库存增减服务是否有效?与邮递员、失眠症、卷曲等客户一起尝试
  • 我渲染了表格,但我尝试使用“添加”和“删除”按钮来增加和减少库存的值,所以我创建了 handleClick 函数来设置库存的新状态,但是当我单击按钮时,应用程序崩溃了。
  • mmmm 所以这是一个反应错误。如果您的问题出现在 handleClick 函数中,并且您的快速端点有效:更新您的问题详细信息,删除所有内容,然后离开反应 handleClick 函数。还要添加类似console.log("im the handleclick") 的日志并修复您的代码,直到此日志显示在您的浏览器控制台上。之后,将其指向您的快速端点。 #3 此外,如果您可以在 github.com/jrichardsz/create-react-app-redux 这样的新反应项目中重现您的错误错误,我们将能够为您提供帮助

标签: node.js reactjs mongoose


【解决方案1】:

handleClick 中的状态更新不正确,它取第 1 个元素值,将其加 1,并将其设置为 this.state.fruits 状态值。这打破了fruits 作为数组的状态不变量。这很可能是您在尝试映射非数组值时看到的“崩溃”。

handleClick =  () => {
  const fruits = [...this.state.fruits]
  this.setState({
    fruits: this.state.fruits[1] +1 // <-- mutates state invariant!!
  })
}

代码也没有传递对它尝试更新的索引或水果的引用。

根据您的架构,水果项目有 3 个属性,namestockprice。对于此解决方案,我将假设 name 具有足够的唯一性以用于识别目的,并且您正在递增/递减 stock 数量。

handleClick = (name, addQuantity = 1) => () => {
  this.setState(prevState => ({
    fruits: prevState.fruits.map(fruit => 
      fruit.name === name
      ? { ...fruit, stock: fruit.stock + addQuantity}
      : fruit
    )
  }));
}

现在您需要在映射时将当前映射的水果项的name 属性传递给处理程序。

{this.state.fruits.map((fruit, index) => (
  <tr key={fruit.name}>
    <th scope="row">{index + 1}</th>
    <td>{fruit.name}</td>
    <td>{fruit.stock}</td>
    <td>{fruit.price}</td>
    <td>
      <div className="mb2">
        <Button
          className="btn btn-primary btn-sm"
          onClick={this.handleClick(item.name, 1)} // <-- add one
        >
          Add
        </Button>{' '}
        <Button
          className="btn btn-danger btn-sm"
          onClick={this.handleClick(item.name, -1)} // remove one
        >
          Remove
        </Button> 
      </div>
    </td>
  </tr>
))}

【讨论】:

  • @AhmedAbdu 这是否解决/解决了您的问题/问题?
猜你喜欢
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多