简单的待办事项列表:前端反应,后端快速。 我是个新手,在激发函数更新数组中包含的单个todo时,我陷入了某种反模式。
我在控制台中记录了请求的结果,您可以在下面看到它。 我也会分享React代码和Express一个,我真的不明白哪里出了问题,我已经卡住了相当一段时间。
在发出补丁呼叫时,实际上会发出一个选项呼叫,如下所示
Request URL: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/3
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 3.11.68.236:3001
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
Allow: PATCH,GET,HEAD,DELETE
Connection: keep-alive
Content-Length: 21
Content-Type: text/html; charset=utf-8
Date: Mon, 22 Jun 2020 11:58:53 GMT
ETag: W/"15-jHsDAtM3pLnwtbz4TiFr85EHmew"
X-Powered-By: Express
Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: PATCH
Origin: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000
Referer: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000/?
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
之后,通过以下方式发出补丁呼叫:
Request URL: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/3
Request Method: PATCH
Status Code: 404 Not Found
Remote Address: 3.11.68.236:3001
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Mon, 22 Jun 2020 11:58:53 GMT
X-Powered-By: Express
Request Headers
Provisional headers are shown
Accept: application/json
Content-type: application/json
Origin: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000
Referer: http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:5000/?
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
Request Payload
{title: "new todo"}
title: "new todo"
我理解OPTIONS调用是作为检查http请求是否合法的一种手段进行的,但为什么我的实际补丁请求包含在OPTIONS调用中(如content-length:21所示),而补丁请求具有content length:0呢?
此外,我不明白为什么我会遇到这种行为,在补丁呼叫中的内容长度为0,但在请求有效载荷中有实际的内容。
下面是React代码:
import React, {Component} from 'react';
class App extends Component {
constructor(){
super();
this.state = { todos:[],
currentItem: ''
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.deleteItem=this.deleteItem.bind(this);
this.updateTodo=this.updateTodo.bind(this);
}
handleInputChange = (e) => this.setState({ currentItem: e.target.value });
handleSubmit(event) {
event.preventDefault();
fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/post', {
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-type': 'application/json'},
body: JSON.stringify({title: this.state.currentItem})
})
.then(res => res.json())
//.then(data => console.log(data))
.then(data => {
this.setState({
todos: [...this.state.todos, data.todo]
})
})
//console.log(this.state)
}
updateTodo(y){
fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/' + y, {
method: 'PATCH',
headers:{
'Accept': 'application/json',
'Content-type': 'application/json'},
body: JSON.stringify({title: this.state.currentItem}),
})
.then(res => console.log(res))
//.then(data => {
// this.setState({
// todos: this.state.todos.forEach(
// item => {
// if(item.key === y){item.title = this.state.currentItem}
// })
// })
// })
}
deleteItem(x){
fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/' + x, {
method: 'DELETE',
headers:{
'Accept': 'application/json',
'Content-type': 'application/json'}
})
.then(res => res.json())
.then(data => {
this.setState({
todos: this.state.todos.filter (t => t.key !== x)
})
})
}
componentDidMount(){
fetch('http://ec2-3-11-68-236.eu-west-2.compute.amazonaws.com:3001/list')
.then(res => res.json())
.then((todos) => {
this.setState({todos: todos});
});
}
render() {
return(
<div>
<h1> Todo List </h1>
<form onSubmit={this.handleSubmit}>
<input
type ="text"
value = {this.state.currentItem}
onChange = {this.handleInputChange}
/>
<input type="submit" value="ADD TODO" />
</form>
<ul>
{this.state.todos.map((todo) => (
<li key = {todo.key}> {todo.title}
<button onClick = {() => this.deleteItem(todo.key)}>x</button>
<button onClick = {() => this.updateTodo(todo.key)}>update</button>
</li>
))}
</ul>
</div>
)
}
}
export default App
我认为,如果响应包含正确的json响应,注释掉的部分将起作用,因为现在我已经注释掉了它们,因为我似乎无法正确地发出补丁请求。 奇怪的是,正确的todo(请求中包含id的todo)确实得到了正确的更新。 我还尝试了动词PUT,结果没有任何差异。
而这是快速代码:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
var counter = 3
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "*");
res.header("Access-Control-Allow-Methods", "*")
next();
});
var todos = [{key:1, title:'eat'}, {key:2, title:'pray'}, {key:3, title:'love'}];
app.listen(3001, function (err) {
if (err) {
console.error('Cannot listen at port 3001', err);}
console.log('Todo app listening at port 3001');
});
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
//GET the whole todos list
app.get('/list', (req, res) => res.status(200).json(todos));
//POST a new todo to the list
app.post('/post', (req, res) => {
if(!req.body.title) {
return res.status(400).send({
success: 'false',
message: 'title is required'
});
}
counter ++;
const todo = {
key: counter,
title: req.body.title
}
todos.push(todo);
return res.send({todo})
});
//PUT to UPDATE a single item
app.patch('/:key', (req, res) => {
var title = req.body.title
var key = parseInt(req.params.key, 10);
for (var i = 0; i < todos.length; i++){
if (todos[i].key === key){
todos[i].title = title;
break;
res.status(200).send({
success: 'true',
message: 'Todo updated successfully'
})
}else {res.status(404, 'The task was not found').send()}
};
});
//GET a single item
app.get('/:key', (req, res) => {
const key = parseInt(req.params.key, 10);
todos.map((todo) => {
if (todo.key === key) {
return res.status(200).send({todo});
}
});
return res.status(404).send({
success: 'false',
message: 'todo does not exist',
});
});
//DELETE an item by its ID
app.delete('/:key', (req, res) => {
const key = parseInt(req.params.key, 10);
todos.map((todo, index) => {
if (todo.key === key) {
todos.splice(index, 1);
return res.status(200).send({
success: 'true',
message: 'Todo deleted successfully',
});
}
});
return res.status(404).send({
success: 'false',
message: 'todo not found',
});
});
module.exports = app;
在发送状态200响应之前,您有break;
行。 查看在res.send
之后移动它是否有帮助。 正确的条目得到更新这一事实证明,此时执行被缩短了。
options
请求只是一个CORS预执行请求,以查看后端是否接受您的请求源(以及动词,标题等)。 在这里阅读更多。