更改状态并在数据库中更新它

Posted

技术标签:

【中文标题】更改状态并在数据库中更新它【英文标题】: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 这样的新反应项目中重现您的错误错误,我们将能够为您提供帮助 【参考方案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 这是否解决/解决了您的问题/问题?

以上是关于更改状态并在数据库中更新它的主要内容,如果未能解决你的问题,请参考以下文章

即使在状态更改后组件也不会更新

机器人状态临时更改

db更改时在Django中重新加载HTML表

使用 Firebase 从不同的集合中获取数据,并在数据更改时更新 UI

如何根据其他状态更改更新一个状态项?

我在反应本机应用程序中使用 redux 来获取和显示数据,但它没有更新来自后端的数据更改