更改状态并在数据库中更新它
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 个属性,name
、stock
和 price
。对于此解决方案,我将假设 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 这是否解决/解决了您的问题/问题?以上是关于更改状态并在数据库中更新它的主要内容,如果未能解决你的问题,请参考以下文章