javascript 尝试了所有解决方案,为什么会出现此错误?正文:CastError:将值mongoose强制转换为字符串失败

wljmcqd8  于 2022-12-25  发布在  Java
关注(0)|答案(1)|浏览(98)

我尝试了各种解决方案,为什么会出现此错误?完全无法理解
我试图从网站删除cloudinary上传部分。
这意味着用户可以在我的博客张贴没有上传图像。
图像是必要的,所以我试图改变源代码,但这个错误不会消失在任何代价

this.$__.validationError = new ValidationError(this);
[0]                                ^
[0]
[0] ValidationError: Post validation failed: body: Cast to string failed for value "{
[0]   _immutable: {
[0]     allowUndo: true,
[0]     currentContent: {
[0]       entityMap: {},
[0]       blockMap: [Object],
[0]       selectionBefore: [Object],
[0]       selectionAfter: [Object]
[0]     },
[0]     decorator: { _decorators: [Array] },
[0]     directionMap: { idih: 'LTR' },
[0]     forceSelection: false,
[0]     inCompositionMode: false,
[0]     inlineStyleOverride: null,
[0]     lastChangeType: 'insert-characters',
[0]     nativelyRenderedContent: null,
[0]     redoStack: [],
[0]     selection: {
[0]       anchorKey: 'idih',
[0]       anchorOffset: 5,
[0]       focusKey: 'idih',
[0]       focusOffset: 5,
[0]       isBackward: false,
[0]       hasFocus: false
[0]     },
[0]     treeMap: { idih: [Array] },
[0]     undoStack: [ [Object] ]
[0]   }
[0] }" (type Object) at path "body", image.publicId: Path `image.publicId` is required., image.url: Path `image.url` is required.

这是我的postmodel.js,我删除必需的:真。但错误是相同的

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const PostSchema = new Schema(
  {
    title: { type: String, required: true },
    image: { url: { type: String, required: true }, publicId: { type: String, required: true } },
    body: { type: String, required: true },
    likes: [{ type: mongoose.Types.ObjectId, ref: 'User' }],
    unicorns: [{ type: mongoose.Types.ObjectId, ref: 'User' }],
    bookmarks: [{ type: mongoose.Types.ObjectId, ref: 'User' }],
    tags: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Tag' }],
    comments: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Comment' }],
    author: { type: mongoose.Types.ObjectId, required: true, ref: 'User' },
  },
  {
    timestamps: true,
  }
);

module.exports = mongoose.model('Post', PostSchema);

这是我的后控制器,我试图改变和删除上传部分从网站,但我不能后3天。
后控制器.js

const Post = require('../model/Post');
const User = require('../model/User');
const Tag = require('../model/Tag');
const Comment = require('../model/Comment');
const cloudinary = require('../config/cloudinary');
const { uploadToCloudinary } = require('../utils/cloudinary');
const { getPostParams, unCapitalizeFirstLetter } = require('../helpers/string');
const { createTags, updateTags, deleteTags } = require('./tagsController');
const {
    likeNotification,
    removeLikeNotification,
    postNotification,
    removePostNotification,
} = require('./notificationsController');

const createPost = async (req, res) => {
    const { title, file, body, tags, authorUsername } = req.body;

    const { url, public_id: publicId } = await uploadToCloudinary(file, 'Posts');
    const author = await User.findOne({ username: authorUsername }).exec();

    const formattedTags = tags
        .trim()
        .split(',')
        .map(w => w.trim().replace(/ /g, '-'));

    const createdPost = await Post.create({
        title,
        image: { url, publicId },
        body,
        author: author._id,
    });

    author.followers.map(followerId => {
        (async () => {
            await postNotification(author._id, createdPost._id, followerId);
        })();
    });

    await createTags(formattedTags, createdPost);

    author.posts.push(createdPost._id);

    await author.save();

    res.status(200).json(createdPost.toObject({ getters: true }));
};

const getPost = async (req, res) => {
    const author = await User.findOne({ username: req.params.username }).exec();
    const authorId = await author?.toObject({ getters: true }).id;
    const { postTitle, postId } = getPostParams(req.params.postUrl);

    const foundPost = await Post.findOne({
        author: authorId,
        title: postTitle,
        _id: postId,
    })
        .populate('author')
        .populate('comments')
        .populate('tags')
        .exec();

    res.status(200).json(foundPost.toObject({ getters: true }));
};

const getPosts = async (req, res) => {
    const { userId } = req.params;

    const posts = await Post.find(userId ? { bookmarks: userId } : {})
        .sort({ createdAt: -1 })
        .populate('author')
        .populate('tags');
    if (!posts) res.status(204).json('No posts found');

    res.status(200).json(posts.map(post => post.toObject({ getters: true })));
};

const updatePost = async (req, res) => {
    const authorId = await User.findOne({ username: req.params.username }).exec();
    const { postTitle, postId } = getPostParams(req.params.postUrl);

    const { url, public_id: publicId } = await uploadToCloudinary(req.body.image.url, 'Posts');

    await cloudinary.uploader.destroy(req.body.image.publicId);

    req.body.image = { url, publicId };
    const formattedTags = req.body.tags
        .trim()
        .split(',')
        .map(w => w.trim().replace(/ /g, '-'));

    const post = await Post.findOne({
        author: authorId,
        title: postTitle,
        _id: postId,
    })
        .populate('author')
        .populate('tags');

    Object.keys(req.body).map(key => {
        if (key !== 'tags') post[key] = req.body[key];
    });

    await updateTags(formattedTags, post);

    await post.save();

    res.status(200).json(post.toObject({ getters: true }));
};

const deletePostsByUserId = async user => {
    const { _id: userId } = user;

    user.comments.forEach(commentId => {
        (async () => {
            await Post.updateMany({ comments: commentId }, { $pull: { comments: commentId } });
        })();
    });

    const posts = await Post.find({ author: userId }).populate('tags');

    ['likes', 'unicorns', 'bookmarks'].forEach(k => {
        (async () => {
            await Post.updateMany({ [k]: userId }, { $pull: { [k]: userId } });
        })();
    });

    posts.forEach(post => {
        (async () => {
            await deleteTags(
                post.tags.map(({ name }) => name),
                post,
                true
            );
            await cloudinary.uploader.destroy(post.image.publicId);
            await Post.deleteOne({ _id: post._id });
        })();
    });

    await Comment.deleteMany({ author: userId });
};

const deletePost = async (req, res) => {
    const author = await User.findOne({ username: req.params.username }).exec();
    const { postTitle, postId } = getPostParams(req.params.postUrl);

    await cloudinary.uploader.destroy(req.body.publicId);

    const foundPost = await Post.findOne({
        author: author._id,
        title: postTitle,
        _id: postId,
    })
        .populate('tags')
        .exec();

    if (!foundPost) return res.sendStatus(204);

    const comments = await Comment.find({ parentPost: postId }).populate({
        path: 'author',
        populate: 'followers',
    });

    comments.forEach(({ author }) =>
        (async () => {
            author.comments.forEach(comment => author.comments.pull(comment));
        })()
    );
    author.posts.pull(postId);
    await author.save();

    await Comment.deleteMany({ parentPost: postId });

    await deleteTags(
        foundPost.tags.map(({ name }) => name),
        foundPost,
        true
    );

    removePostNotification(author._id, foundPost._id, author.followers);

    await Post.deleteOne({ _id: foundPost._id });

    res.status(200).json(foundPost.toObject({ getters: true }));
};

const postReaction = async (req, res) => {
    const { userId } = req.body;
    const { action, postUrl } = req.params;
    const { postTitle, postId } = getPostParams(postUrl);
    const isUndoing = action.includes('remove');
    const actionKey = isUndoing
        ? unCapitalizeFirstLetter(action.replace('remove', '')) + 's'
        : action + 's';

    const author = await User.findOne({ username: req.params.username }).exec();
    const authorId = await author.toObject({ getters: true }).id;

    const updatedPost = await Post.findOneAndUpdate(
        { author: authorId, title: postTitle, _id: postId },
        isUndoing ? { $pull: { [actionKey]: userId } } : { $addToSet: { [actionKey]: userId } },
        { new: true, timestamps: false }
    );

    if (isUndoing) await removeLikeNotification(userId, updatedPost._id, authorId);
    else await likeNotification(userId, updatedPost._id, authorId);

    res.status(200).json(updatedPost.toObject({ getters: true }));
};

module.exports = {
    createPost,
    getPosts,
    getPost,
    updatePost,
    deletePost,
    deletePostsByUserId,
    postReaction,
};

这是我的前端部分new-post.jsx

import 'easymde/dist/easymde.min.css';
import { useContext, useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import SimpleMDE from 'react-simplemde-editor';
import tw from 'twin.macro';
import Error from '../../common/Error';
import LoadingSpinner from '../../common/LoadingSpinner';
import RouteWrapper from '../../common/RouteWrapper';
import socketContext from '../../context/SocketContext';
import { selectCurrentUser } from '../../core/features/auth/authSlice';
import { useCreatePostMutation } from '../../core/features/posts/postsApiSlice';
import { useGetUserDashboardQuery } from '../../core/features/users/usersApiSlice';
import useBase64 from '../../hooks/useBase64';
import useRequireAuth from '../../hooks/useRequireAuth';
import { Editor } from "react-draft-wysiwyg";
// import "../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
// import React, { Component } from 'react';
import "../NewPost/react-draft-wysiwyg.css"
// import "react-draft-wysiwyg/dist/react-draft-wysiwyg.cs";

// import LiveMarkdown from '../markdowneditor/markdowneditor';
// import  EasyMDE from 'easymde';

const NewPost = () => {
  const [title, setTitle] = useState('');
  const [file, setFile] = useState('');
  const [body, setBody] = useState('');
  const [tags, setTags] = useState('');
  const [isTagsFocused, setIsTagsFocused] = useState(false);
  const [inputsFilled, setInputsFilled] = useState(false);
  const filePickerRef = useRef();
  const titleRef = useRef();
  const [createPost, { isLoading, isError }] = useCreatePostMutation();
  const navigate = useNavigate();
  const currentUser = useSelector(selectCurrentUser);
  const dispatch = useDispatch();
  const previewURL = useBase64(file);
  const { isAuthed, handleAuth } = useRequireAuth();
  const { socket } = useContext(socketContext);
  const { data: user } = useGetUserDashboardQuery(currentUser.username);

  useEffect(() => titleRef.current.focus(), []);

  useEffect(() => {
    if (title && body && tags) setInputsFilled(true);
    else setInputsFilled(false);
  }, [title, body, tags]);

  const handleSubmit = async () => {
    if (inputsFilled) {
      if (isAuthed) {
        try {
          const { id } = await createPost({
            title,
            file: previewURL,
            body,
            tags,
            authorUsername: currentUser.username,
          }).unwrap();

          socket.emit('post', {
            sender: currentUser,
            receivers: user?.followers,
            post: { title, id },
          });

          setTitle('');
          setFile('');
          setBody('');
          setTags('');

          navigate('/');
        } catch (err) {
          console.log(err);
        }
      } else handleAuth();
    }
  };

  return (
    <RouteWrapper>
      <Wrapper>
        {isLoading && <LoadingSpinner />}
        {!isLoading && (
          <NewPostWrapper>
            <Heading>ایجاد پست جدید</Heading>
            <InputWrapper>
              <Label dir='rtl' htmlFor='title'>موضوع</Label>
              <Input
              
                dir='rtl'
                ref={titleRef}
                id='title'
                value={title}
                onBlur={e => setTitle(prev => prev.trim())}
                onChange={e => setTitle(e.target.value)}
                required
              />
            </InputWrapper>
            <InputWrapper>
              // <Input
                type='file'
                ref={filePickerRef}
                onChange={e => setFile(e.target.files[0])}
                style={{ display: 'none' }}
                
              />
              <ImagePreview src={previewURL.toString()} alt='عکس انتخاب کنید' />
              <Button onClick={() => filePickerRef.current.click()}>انتخاب آواتار</Button>
            </InputWrapper>
            <InputWrapper2>

            
              {/* <SimpleMDE value={body} onChange={setBody} required /> */}
              
              <Editor 
               
               
                    
                    editorState={body}
                    toolbarClassName="toolbarClassName"
                    wrapperClassName="wrapperClassName"
                    editorClassName="editorClassName"
                    onEditorStateChange={setBody}
                    textAlignment="right"
                    placeholder="اینجا تایپ کنید"
                />;



            </InputWrapper2>
            <InputWrapper>
              <Label htmlFor='tags'>
                تگ ها
                {isTagsFocused && (
                  <Span>تگ ها با کاما جدا شده هست</Span>
                )}
              </Label>
              <Input
                id='tags'
                value={tags}
                onFocus={() => setIsTagsFocused(true)}
                onBlur={() => setIsTagsFocused(false)}
                onChange={e => setTags(e.target.value.replace(/ /g, ''))}
                required
              />
            </InputWrapper>
            <Submit onClick={handleSubmit}>تایید</Submit>
            {isError && <Error>خطاا در انجام عملیات . دوباره امتحان کنید</Error>}
            {!inputsFilled && <Error>تمام فیلدها اجباری هست</Error>}
          </NewPostWrapper>
        )}
      </Wrapper>
    </RouteWrapper>
  );
};

const Submit = tw.button`bg-lighter-gray hover:bg-light-gray rounded-md text-center py-2 px-1 w-full text-sm`;

const ImagePreview = tw.img`w-32 h-32 mx-auto border border-gray flex justify-center items-center text-center object-cover`;

const Input = tw.input`py-1 px-2 rounded-md outline-none border-2 border-solid border-gray focus:border-blue`;

const Label = tw.label`font-bold text-dark-gray`;

const Span = tw.p`inline ml-sm`;

const InputWrapper = tw.div`flex flex-col gap-2  `;

const Button = tw.button`bg-lighter-gray hover:bg-light-gray rounded-md text-center py-2 px-1 w-28 text-sm mx-auto`;

const Heading = tw.h1`text-dark-gray text-center`;

const NewPostWrapper = tw.div`bg-white w-3/5 mob:(w-full px-4) mx-auto py-20 px-8 [&>*:not(:last-child)]:mb-md`;

const Wrapper = tw.div`flex items-center`;

const InputWrapper2 = tw.div`border border-gray`;

export default NewPost;

我试图删除文件更改和更改。但这个错误不会消失。请如果有人知道这个答案帮助我

kxe2p93d

kxe2p93d1#

当您尝试创建一个没有值的帖子时,会发生此错误,但在您的架构中,您已根据需要设置了标题、正文等的值,因此出现此错误,请检查您是否正在从前端调用创建帖子,但没有值。
试着检查一下这个useEffect,在这里你设置了你的inputsfilled,我敢打赌,即使值是空的,它也会设置inputsfilled为真。

useEffect(() => {
    if (title && body && tags) setInputsFilled(true);
    else setInputsFilled(false);
  }, [title, body, tags]);

后端错误是因为您尝试使用所需参数创建Post,但参数值为空。
希望这能有所帮助。这甚至可能不是问题所在。如果我弄错了,我的错。

相关问题