У меня проблема с моим PUT
методом. Я использую ax ios и хочу обновить свой «проект». Для этого я использую форму, передаю все данные, и я попадаю на свой маршрут /projects/update/5f0d5f963a82457bc418d03d
, где последняя часть - это идентификатор проекта, который я получаю.
Так что в моем компоненте UpdateProject нет ничего особенного:
import React, { Component, Fragment } from 'react';
import axios from 'axios';
import Button from '../../common/Buttons/Button';
import Spinner from '../../common/Spinner/Spinner';
import { API_URL } from '../../../config';
import { isAuthUser } from '../../../utils/utils';
class ProjectUpdate extends Component {
state = {
formData: {
creator: '',
title: '',
description: '',
shortDescription: '',
photo: '',
tags: '',
projectType: '',
links: {},
},
displayLinks: false,
loading: false,
};
componentDidMount() {
this.ftechId();
}
ftechId = async () => {
this.setState({ loading: true });
try {
await axios
.get(`${API_URL}/projects/${this.props.match.params.projectId}`)
.then((res) =>
this.setState({
formData: res.data,
loading: false,
})
);
} catch (err) {
console.log(err);
}
};
updateProject = async (formData) => {
this.setState({ loading: true });
const { token } = isAuthUser();
const config = {
headers: {
Accept: 'application/json',
Authorization: `${token}`,
},
};
try {
console.log('formdata update', formData);
await axios
.put(
`${API_URL}/projects/update/${this.props.match.params.projectId}`,
formData,
config
)
.then((res) => console.log('res', res));
this.setState({ loading: false });
} catch (err) {
console.log(err);
}
};
onChange = (e) => {
// setting formData in the state properly
const { formData } = this.state;
let newFormData = { ...formData };
newFormData[e.target.name] = e.target.value;
this.setState({
formData: newFormData,
});
};
onSubmit = (e) => {
const { formData } = this.state;
const fileToUpload = document.querySelector('#photoID');
const sendData = new FormData();
sendData.append('title', formData.title);
sendData.append('description', formData.description);
sendData.append('photo', fileToUpload.files[0]);
sendData.append('tags', formData.tags);
sendData.append('projectType', formData.projectType);
sendData.append('shortDescription', formData.shortDescription);
sendData.append('git', formData.git);
sendData.append('demo', formData.demo);
sendData.append('creator', formData.creator);
console.log('sendData', formData.tags);
e.preventDefault();
this.updateProject(sendData);
};
toggleLinks = () => {
const { displayLinks } = this.state;
if (!displayLinks) {
this.setState({ displayLinks: true });
} else {
this.setState({ displayLinks: false });
}
};
renderProject = () => {
const {
loading,
displayLinks,
formData: {
title,
description,
shortDescription,
photo,
tags,
projectType,
links,
},
} = this.state;
console.log('state form', this.state.formData);
if (loading === true) {
return <Spinner />;
} else {
return (
<section className=''>
<h1 className=''>Update Project</h1>
<p className=''>
<i className='fas fa-user'></i> Add project information
</p>
<small>* = required field</small>
<form
encType='multipart/form-data'
className='form'
onSubmit={(e) => this.onSubmit(e)}>
<div className=''>
<select
name='projectType'
value={projectType}
onChange={this.onChange}>
<option value='0'>* Select Project Type Status</option>
<option value='Front-end'>Front-end</option>
<option value='Back-end'>Back-end</option>
<option value='MERN'>MERN</option>
<option value='Vanila JS'>Vanila JS</option>
<option value='html'>HTML/CSS</option>
</select>
<small className='form-text'>Select a project type.</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Title'
name='title'
value={title}
onChange={this.onChange}
/>
<small className='form-text'>Add project title.</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Description'
name='description'
value={description}
onChange={this.onChange}
/>
<small className='form-text'>Add project description</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Short description'
name='shortDescription'
value={shortDescription}
onChange={this.onChange}
/>
<small className='form-text'>Add project short description</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='* Tags'
name='tags'
value={tags}
onChange={this.onChange}
/>
<small className='form-text'>
Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
</small>
</div>
<div className='form-group'>
<input
id='photoID'
type='file'
accept='.jpg, .png, .jpeg'
placeholder='Photo'
name='photo'
// value={photo}
onChange={this.onChange}
/>
<small className='form-text'>Add project preview.</small>
</div>
<div className='my-2'>
<button onClick={this.toggleLinks} type='button' className=''>
Add Project Links
</button>
<span>Optional</span>
{displayLinks && (
<div>
<div className=''>
<i className=''></i>
<input
type='text'
placeholder='Git URL'
name='git'
value={links.git}
onChange={this.onChange}
/>
</div>
<div className=''>
<i className=''></i>
<input
type='text'
placeholder='Demo URL'
name='demo'
value={links.demo}
onChange={this.onChange}
/>
</div>
</div>
)}
</div>
<input type='submit' className='btn btn-primary my-1' />
<Button className='btn btn-light my-1' to='/projects'>
Go Back
</Button>
</form>
</section>
);
}
};
render() {
return <Fragment>{this.renderProject()}</Fragment>;
}
}
export default ProjectUpdate;
Здесь я набираю projects/${this.props.match.params.projectId}
, чтобы получить данные моего проекта. Я добавляю данные в const sendData = new FormData();
и хочу отправить их на свой mongoDB. Из моего console.logs
все данные в состоянии до моего обновления и после обновления. Для обновления я использую этот маршрут:
updateProject = async (formData) => {
this.setState({ loading: true });
const { token } = isAuthUser();
const config = {
headers: {
Accept: 'application/json',
Authorization: `${token}`,
},
};
try {
console.log('formdata update', formData);
await axios
.put(
`${API_URL}/projects/update/${this.props.match.params.projectId}`,
formData,
config
)
.then((res) => console.log('res', res));
this.setState({ loading: false });
} catch (err) {
console.log(err);
}
};
Я запутался здесь, потому что из моего ответа, который у меня есть на вкладке «Сеть» на f12, я вижу, что заголовки установлены на новое значение, но сам ответ не изменяется так как мои данные никогда не были snet в db.
Итак, я начинаю копать на моем бэкэнде. В моем маршруте нет ничего особенного
router.put(
'/projects/update/:projectId',
authCheck,
isAdmin,
findProjectById,
update
);
Я проверяю здесь, если пользователь является администратором и имеет JWT токен. После того, как я нажал update
exports.update = (req, res) => {
let form = new formidable.IncomingForm();
console.log(form);
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
if (err) {
return res
.status(400)
.json({ errors: [{ msg: 'Image could not be uploaded' }] });
}
// const { git, demo } = fields;
// fields.creator = req.user._id;
// fields.links = {};
// if (git) fields.links.git = git;
// if (demo) fields.links.demo = demo;
let project = req.project;
console.log('project', project);
console.log('req.proj', req.project);
//1kb = 1000
//1mb = 1000000kb
//name 'photo' mus match client side. use photo
if (files.photo) {
if (files.photo.size > 1000000) {
return res.status(400).json({
errors: [{ msg: 'Image could not be uploaded. File to big.' }],
});
}
//this relates to data in schema product
project.photo.data = fs.readFileSync(files.photo.path);
project.photo.contentType = files.photo.type;
}
console.log('project update', fields);
project.save();
return res.json(project);
});
};
Здесь из моего console.logs
я вижу, что получаю свой проект, когда нажимаю findProjectById, getProject
, но похоже, что все останавливается и не движется к update
/* find project by id */
exports.findProjectById = async (req, res, next) => {
const id = req.params.projectId;
try {
let project = await Project.findById(id);
if (!project) return res.status(400).json({ msg: 'Porject not found' });
req.project = project;
next();
} catch (err) {
console.error(err.message);
if (err.kind === 'ObjectId') {
return res.status(400).json({ msg: 'Porject not found' });
}
res.status(500).send('Server Error');
}
};
Мой req.project
возвращает проект, который я хочу обновить, а console.log('proejct update')
- это возвращаемые данные, которые я хочу отправить и сохранить, но ничего не происходит. Не уверен, где искать, чтобы это заработало. Я проверял другие похожие проблемы здесь, но у меня ничего не работало
Изменить: после нажатия обновления я получаю ответ 200 для моего PUT
, других ошибок нет, но данные не обновлены в БД My ${API_URL}/projects/update/${this.props.match.params.projectId}
совпадает с идентификатором моего проекта и маршрутом для обновления
данные формы