我有一个多部分的表单,我正在使用formData发送一个'PUT'请求的数据.我得到了错误Cast to objectId failed for value 'undefined' (type string) at path '_id' for model 'Blogpost',当我在控制器上console.logreq.params.id时,它返回undefined. 我使用react-hook-form,redux-toolkit和multer-cloudinary来上传图片.
我的前端是:
const BlogpostEdit = () => {
const { id } = useParams()
const {
data: blogpostData,
isLoading,
refetch,
error
} = useGetBlogpostDetailsQuery(id)
const [updateBlogpost, { isLoading: loadingUpdate }] =
useUpdateBlogpostMutation()
useEffect(() => {
if (blogpostData) {
setValue('image', blogpostData.image)
setValue('title', blogpostData.title)
setValue('subtitle', blogpostData.subtitle)
setValue('content', blogpostData.content)
setValue('category', blogpostData.category)
}
}, [blogpostData])
const {
register,
setValue,
handleSubmit,
formState: { errors }
} = useForm()
const onFormSubmit = async data => {
if (data.image[0]) {
const formData = new FormData()
formData.append('_id', id)
formData.append('image', data.image[0])
data = { ...data, image: data.image[0].name }
formData.append('image', data.image)
formData.append('title', data.title)
formData.append('subtitle', data.subtitle)
formData.append('content', data.content)
formData.append('category', data.category)
try {
const response = await updateBlogpost(formData).unwrap()
toast.success('Blogpost has been updated')
refetch()
} catch (err) {
toast.error(err?.data?.message || err.error)
}
} else {
try {
const response = await updateBlogpost({ ...data, _id: id }).unwrap()
toast.success('Blogpost has been updated')
refetch()
} catch (err) {
toast.error(err?.data?.message || err.error)
}
}
}
return (
<FormContainer>
{loadingUpdate && <Loader />}
{isLoading ? (
<Loader />
) : error ? (
<p>{error.data.message}</p>
) : (
<>
<img src={blogpostData.image.url} style={{ width: '150px' }} />
<form onSubmit={handleSubmit(onFormSubmit)}>
<label htmlFor='image' name='image'>
image
</label>
<input type='file' {...register('image')} />
<p>{errors.image?.message}</p>
<label htmlFor='title' name='title'>
Title
</label>
<input type='text' {...register('title')} />
<p>{errors.title?.message}</p>
<label htmlFor='subtitle' name='subtitle'>
Subtitle
</label>
<input type='text' {...register('subtitle')} />
<p>{errors.subtitle?.message}</p>
<label htmlFor='content' name='content'>
Content
</label>
<textarea
rows='10'
cols='100'
type='text'
{...register('content')}
/>
<p>{errors.content?.message}</p>
<label htmlFor='category'>Choose a category:</label>
<select name='category' {...register('category')}>
<option value=''></option>
<option value='game'>Game</option>
<option value='tv'>TV</option>
<option value='anime'>Anime</option>
<option value='book'>Book</option>
</select>
<p>{errors.category?.message}</p>
<button type='submit'>Submit</button>
</form>
</>
)}
</FormContainer>
)
}
export default BlogpostEdit
切片/Mutations 是:
updateBlogpost: builder.mutation({
query: (data) => ({
url: `${BLOGPOSTS_URL}/${data._id}`,
method: 'PUT',
body: data,
}),
invalidatesTags: ['Blogposts'],
}),
后端控制器:
const updateBlogpost = asyncHandler(async (req, res) => {
const { id } = req.params;
const blogpost = await Blogpost.findByIdAndUpdate(id, { ...req.body });
if (req.file) {
blogpost.image.url = req.file.path;
blogpost.image.filename = req.file.filename;
}
const updatedBlogpost = await blogpost.save();
if (updatedBlogpost) {
res.status(200).json(updatedBlogpost);
} else {
res.status(404);
throw new Error('Resouce not found');
}
});
路由:
router
.route('/:id')
.put(registered, admin, upload.single('image'), updateBlogpost);
提交表格的数据看起来像这样:
和formData:
这是控制台上的错误:
try/catch的错误:
在控制器上,我得到了req.body,图像成功上传,但req.params.id未定义.如果我不添加一个图像,只是编辑标题,例如,一切工作.当我想包含图像时,会发生这些错误.我在"POST"请求上使用了完全相同的代码,它工作得很好. 现在我知道我可以先上传文件使用不同的上传路径和不同的路径来更新模型,但我就是不知道为什么会发生这些错误.