这让我发疯。我现在调试了一个星期,仍然无法修复此代理错误。但是有一个陷阱。我在api端点中发送的数据仍保存在数据库中。
这就是我得到的。
我有一个react组件,可以处理公告的输入。该组件还处理文件上传。
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { addAnnouncement } from '../../actions/announcementActions';
import moment from 'moment';
function AddEventForm(props){
const classes = styles();
/* States*/
const [values, setValues] = useState({
title: '',
venue: '',
description: '',
bgColor:'#000000',
});
const [poster, getPoster] = useState({
poster: null,
fileName: ''
});
const [selectedDate, setSelectedDate] = useState(new Date());
const [selectedTime, setSelectedTime] = useState(new Date());
const [errors, getErrors] = useState({});
/* Event Handlers*/
const handleDate = date => {
setSelectedDate(date);
}
const handleTime = time => {
setSelectedTime(time);
}
const handleSubmit = e => {
e.preventDefault();
// const fullDate = `${selectedDate.getFullYear()}-${selectedDate.getMonth() + 1}-${selectedDate.getDate()}`;
const dateDate = moment(selectedDate).format('YYYY-MM-DD');
const dateTime = moment(selectedTime).format('HH:mm:ss');
const date = `${dateDate} ${dateTime}`;
const newAnnouncement = {
...values,
...poster,
date,
dateDate,
dateTime,
setBy: 'SOA Admin'
}
let fd = new FormData();
fd.append('poster', poster.poster);
fd.append('title', values.title);
fd.append('venue', values.venue);
fd.append('description', values.description);
fd.append('fileName', poster.fileName);
fd.append('bgColor', values.bgColor);
fd.append('date', date);
fd.append('dateDate', dateDate);
fd.append('dateTime', dateTime);
fd.append('setBy', 'SOA Admin');
// console.log(newAnnouncement);
// console.log(_formData);
props.addAnnouncement(fd);
}
// Component Effect for a successful Adding of Announcement
useEffect(_ => {
if(props.announcement.added)
props.history.push('/ad/announceevent');
},[props.announcement.added]);
// Component Effect for the errors
useEffect(_ => {
if(props.errors)
getErrors(props.errors)
},[props.errors])
console.log(props);
return (
<div>
<DashboardAdmin>
<Breadcrumbs aria-label="breadcrumb" style={{ paddingBottom: '20px'}}>
<Link color="inherit" href="/ad/announceevent" className={classes.link}>
<ViewListIcon className={classes.icon} />
Menu
</Link>
<Link
color="textPrimary"
href="/ad/announceevent/addevent"
aria-current="page"
className={classes.link}
>
<ListAltIcon className={classes.icon} />
Add
</Link>
</Breadcrumbs>
<Paper className={classes.root}>
<Container maxWidth="lg">
<Typography variant="h4" align="center">
Announce Event Form
</Typography>
<br></br>
<form noValidate onSubmit={handleSubmit} enctype="multipart/form-data">
<Typography variant="h6">
Input the details needed.
</Typography>
<Grid item xs={12}>
<TextField
value={values.title}
onChange={e => setValues({...values, title: e.target.value})}
id="title"
name="title"
label="Announcement/Event Title"
fullWidth
autoComplete
/>
</Grid>
<span style={{ color: "red" }}>
{errors.title}
</span>
<br />
<Grid item xs={12}>
<FormControl fullWidth className={classes.formControl}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
value={selectedDate}
onChange={handleDate}
disableToolbar
variant="inline"
format="yyyy-MM-dd"
margin="normal"
id="date-picker-inline"
label="Date of the event"
KeyboardButtonProps={{
'aria-label': 'change date',
}}
/>
</MuiPickersUtilsProvider>
</FormControl>
</Grid>
<span style={{ color: "red" }}>
{errors.date}
</span>
<br />
<Grid item xs={12}>
<FormControl fullWidth className={classes.formControl}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardTimePicker
format= "hh:mm a"
value={selectedTime}
onChange={handleTime}
margin="normal"
id="time-picker"
label="Time picker"
KeyboardButtonProps={{
'aria-label': 'change time',
}}
keyboardIcon={<AccessTimeIcon />}
/>
</MuiPickersUtilsProvider>
</FormControl>
</Grid>
<br/>
<Grid item xs={12}>
<TextField
value={values.venue}
onChange={e => setValues({...values, venue: e.target.value})}
id="venue"
name="venue"
label="Where the event will happen"
fullWidth
autoComplete
/>
</Grid>
<span style={{ color: "red" }}>
{errors.venue}
</span>
<br />
<Grid container spacing={1} alignItems="flex-end">
<Grid item xs={1}>
{/*
onChange={e => setObj({...obj, file: e.target.files[0], fileName: e.target.files[0].name})}
value={obj.fileName}
*/}
<input
onChange={e => getPoster({...poster, poster: e.target.files[0], fileName: e.target.files[0].name.toLowerCase().split(' ').join('-')})}
className={classes.input} id="poster" name="poster" type="file" />
<label htmlFor="poster">
<IconButton color="primary" aria-label="upload picture" component="span">
<CloudUploadIcon />
</IconButton>
</label>
</Grid>
<Grid item xs={11}>
<TextField
value={poster.fileName}
id="input-with-icon-grid"
label="Poster for the event"
helperText="Note: .png and .jpg is required"
fullWidth
InputProps={{
readOnly: true,
}}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
</Grid>
<span style={{ color: "red" }}>
{errors.poster}
</span>
<br />
<Grid container spacing={1} alignItems="flex-end">
<Grid item xs={8}>
<TextField
value={values.description}
onChange={e => setValues({...values, description: e.target.value})}
id="description"
name="description"
label="Description of the Event"
fullWidth
autoComplete
multiline
/>
</Grid>
<br/>
<span style={{ color: "red" }}>
{errors.description}
</span>
<Grid item xs={4}>
<TextField
type="color"
value={values.bgColor}
onChange={e => setValues({...values, bgColor: e.target.value})}
id="color"
name="color"
label="Choose color for the display background of the event"
fullWidth
autoComplete
/>
</Grid>
</Grid>
<Button
type="submit"
variant="outlined"
color="secondary"
className={classes.submit}
>
Add Record
</Button>
</form>
</Container>
</Paper>
</DashboardAdmin>
</div>
)
}
const mapStateToProps = state => ({
announcement: state.announcement,
errors: state.errors,
});
const mapDispatchToProps = { addAnnouncement };
export default connect(mapStateToProps, mapDispatchToProps)(AddEventForm);
然后这就是我的动作
export const addAnnouncement = data => dispatch => {
axios.post('/api/announcements/addEvents', data)
.then(res => dispatch({
type: ADD_ANNOUNCEMENT_ADMIN,
payload: res.data,
}))
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
}
那么这就是减速器
import {
ADD_ANNOUNCEMENT_ADMIN,
} from '../actions/types';
const initialState = {
added: false,
};
const initialState = {
added: false,
updated: false,
deleted: false,
};
export default function(state = initialState, action) {
switch(action.type) {
case ADD_ANNOUNCEMENT_ADMIN:
return {
...state,
added:true
};
//....
default:
return state;
}
};
这是我到达api端点/ addEvents
的路线const express = require('express');
const router = express.Router();
const multer = require('multer');
const path = require('path');
//The directory where the files will be stored
const DIR = 'client/public/announcements/';
const Announcements = require('../../models/announcements.model');
const validateAnnouncements = require('../../validation/announcements');
//Diskstorage for sending the files into the assigned Directory
const storage = multer.diskStorage({
// The destination of the file
destination: (req, file, cb) => {
cb(null, DIR)
},
// what will be the filename of the file uploaded
filename: (req, file, cb) => {
// the filename format
const filename = file.originalname.toLowerCase().split(' ').join('-');
cb(null, `${filename}`);
}
});
const upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if(file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
}
else {
cb(null, false)
}
}
});
//@route POST /api/announcements/addEvents
//@desc Add a announcements data
//@access SOA Admin and SOA Head
router.post('/addEvents', upload.single('poster'), (req, res) => {
const poster = req.file;
//Url of the app
const url = req.protocol + '://' + req.get('host');
const today = new Date();
const { errors, isValid } = validateAnnouncements(req.body);
if(!isValid) {
return res.status(400).json(errors);
}
else if(poster === undefined) {
return res.status(400).json({poster: 'Pictures only'})
}
else {
const title = req.body.title;
const date = req.body.date;
const dateDate = req.body.dateDate;
const dateTime = req.body.dateTime;
const venue = req.body.venue;
const description = req.body.description;
const backgroundColor = req.body.bgColor;
const setBy = req.body.setBy;
const fileName = req.body.fileName;
const newAnnouncements = new Announcements({
title,
date,
dateDate,
dateTime,
backgroundColor,
venue,
description,
poster: url + '/' + poster.path,
fileName,
setBy,
created_at: today
});
newAnnouncements.save()
.then(response => res.json({
message:'Request submitted',
datas: {response}
}))
.catch(err => res.status(500).json(err));
}
// console.log(newAnnouncements);
});
我不知道我的应用出现代理错误的原因。
这是错误消息
Proxy error: Could not proxy request /api/announcements/addEvents from localhost:8000 to http://localhost:6000.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNRESET).
这是我在react中的package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"@date-io/date-fns": "^1.3.13",
"@fullcalendar/core": "^5.1.0",
"@fullcalendar/daygrid": "^5.1.0",
"@fullcalendar/interaction": "^5.1.0",
"@fullcalendar/react": "^5.1.0",
"@material-ui/core": "^4.7.1",
"@material-ui/icons": "^4.5.1",
"@material-ui/lab": "^4.0.0-alpha.48",
"@material-ui/pickers": "^3.2.10",
"@material-ui/system": "^4.9.6",
"axios": "^0.19.2",
"classnames": "^2.2.6",
"fullcalendar": "^5.1.0",
"jwt-decode": "^2.2.0",
"moment": "^2.24.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.2.0",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "PORT=8000 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:6000",
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
这使我花了一个星期来调试它,但仍然无法解决为什么它出现代理错误。感觉像是客户端崩溃了。但是仍然在保存数据。然后,它只会刷新应用程序本身。
提供有关如何解决此问题的建议和帮助,将不胜感激。