محمود سعداوي2 نشر 9 يونيو أرسل تقرير نشر 9 يونيو السلام عليكم. في المثال التالي، أواجه الأخطاء التالية: عندما أضيف Review معين (بين 1 و 5) فإنه يتم إرسال عدد أكبر من 5 إلى قاعدة البيانات لايتم إضافة التقييم إلى واجهة الصفحة إلا بعد التحديث الكود bookController // method POST // route api/books/:id/reviews // desc Add a book review // access Private | auth const addReview = asyncHandler(async(req, res) => { const { id } = req.params const { comment, rate } = req.body const book = await Book.findById(id) const user = await User.findById(req.userId) if (!book) { return res.status(404).json({ message: "Book Not Found" }) } const isRated = book.reviews.findIndex(m => m.user == req.userId) if (isRated > -1){ return res.status(403).send({ message: "Review Is Already Added" }); } const totalRate = book.reviews.reduce((sum, review) => sum + review.rate ,0) const finalRate = (totalRate + rate) / (book.reviews.length + 1) await Book.updateOne( { _id: id } , { $push: { reviews: { user: req.userId, username: user.name, comment, rate } }, $set: { rate: finalRate } } ) res.status(201).json({ message: "Review added successfully" }) }) Frontend apiCall // Post Review export function postReview(bookId, review) { return async (dispatch, getState) => { try { dispatch(bookActions.setLoading()) const {data} = await axios.post(`${BOOK_URL}/${bookId}/reviews`, review, { headers: { "authorization": getState().auth.user.accessToken } }); toast.success(data?.message) dispatch(bookActions.addReviews()); dispatch(bookActions.clearLoading()); } catch (error) { toast.error(error?.response?.data.message); dispatch(bookActions.clearLoading()); } }; } bookSlice const bookSlice = createSlice({ name: "book", initialState: { books: [], error: false, loading: false, }, reducers: { getBooks(state, action) { state.books = action.payload; }, findBook(state, action) { state.books = action.payload; }, addReviews(state, action) { state.books = action.payload; }, setLoading(state) { state.loading = true; }, clearLoading(state) { state.loading = false; }, setError(state) { state.error = true; }, clearError(state) { state.error = false; }, } } Component const Modal = ({ showModal, handleClose, book }) => { const [rate, setRating] = useState(0); const [comment, setComment] = useState(""); const dispatch = useDispatch(); const navigate = useNavigate(); const submitReview = (e) => { e.preventDefault(); if (comment === "") { return toast.error("Comment is required") } dispatch(postReview(book, { rate, comment })) navigate(`/${book}`) }; return ( <div className={`modal ${showModal ? "show" : ""}`}> <div className="modal-content"> <span className="close" onClick={handleClose}>×</span> <h2>Submit Your Review</h2> <form onSubmit={submitReview}> <div className="rating-input"> <label>Rating:</label> <select value={rate} onChange={(e) => setRating(e.target.value)} required> <option value="" disabled>Select a rating</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> </div> <div className="comment"> <label>Comment:</label> <textarea value={comment} onChange={(e) => setComment(e.target.value)}/> </div> <button className='modal-btn' type="submit">Submit</button> </form> </div> </div> ); }; export default Modal; شكرا على المساعدة اقتباس
0 Mustafa Suleiman نشر 9 يونيو أرسل تقرير نشر 9 يونيو أولاً لديك خطأ في حساب متوسط التقييمات في السطر الذي يحسب فيه المتوسط النهائي finalRate. فالمتغير rate ربما يتم إرساله كقيمة غير صحيحة مثل قيمة نصية من الواجهة الأمامية، لذا لنتأكد من أن rate يتم تحويله إلى رقم صحيح قبل استخدامه في الحساب، وأيضًا التأكد من صحة قيم التقييم المرسلة من الواجهة الأمامية. أيضًا بعد إضافة المراجعة إلى قاعدة البيانات، عليك إعادة بيانات الكتاب المحدثة إلى الواجهة الأمامية، بما في ذلك التقييم الجديد، وبعد تلقي بيانات الكتاب المحدثة من الخادم، يجب تحديث حالة الكتاب في الواجهة الأمامية لتعكس التقييم الجديد. ثم استخدام البيانات المحدثة للكتاب في المكون لعرض التقييم الجديد. إليك التعديلات مع تعليقات لتوضيح أماكن التعديل. تعديل في bookController.js: const addReview = asyncHandler(async(req, res) => { const { id } = req.params const { comment, rate } = req.body const book = await Book.findById(id) const user = await User.findById(req.userId) // التحقق من وجود الكتاب if (!book) { return res.status(404).json({ message: "Book Not Found" }) } // التحقق من أن المستخدم لم يقيم الكتاب مسبقاً const isRated = book.reviews.findIndex(m => m.user == req.userId) if (isRated > -1){ return res.status(403).send({ message: "Review Is Already Added" }); } // تحويل تقييم المستخدم إلى رقم صحيح والتحقق من صحته const numericRate = parseInt(rate, 10); if (isNaN(numericRate) || numericRate < 1 || numericRate > 5) { return res.status(400).send({ message: "Invalid rating value" }); } // حساب التقييم النهائي const totalRate = book.reviews.reduce((sum, review) => sum + review.rate ,0) const finalRate = (totalRate + numericRate) / (book.reviews.length + 1) // تحديث بيانات الكتاب بإضافة المراجعة الجديدة وتحديث التقييم await Book.updateOne( { _id: id }, { $push: { reviews: { user: req.userId, username: user.name, comment, rate: numericRate } }, $set: { rate: finalRate } } ) // إعادة بيانات الكتاب المحدثة بعد الإضافة const updatedBook = await Book.findById(id); res.status(201).json(updatedBook) }) تحديث الدالة postReview في apiCall: export function postReview(bookId, review) { return async (dispatch, getState) => { try { dispatch(bookActions.setLoading()) const {data} = await axios.post(`${BOOK_URL}/${bookId}/reviews`, review, { headers: { "authorization": getState().auth.user.accessToken } }); // عرض رسالة نجاح باستخدام toast toast.success(data?.message) // تحديث بيانات الكتاب المحدثة في الحالة dispatch(bookActions.updateBook(data)); dispatch(bookActions.clearLoading()); } catch (error) { // عرض رسالة خطأ باستخدام toast toast.error(error?.response?.data.message); dispatch(bookActions.clearLoading()); } }; } تعديل في الواجهة الأمامية Modal.js const Modal = ({ showModal, handleClose, book }) => { const [rate, setRating] = useState(0); const [comment, setComment] = useState(""); const dispatch = useDispatch(); const navigate = useNavigate(); const submitReview = (e) => { e.preventDefault(); if (comment === "") { // التحقق من وجود تعليق وعرض رسالة خطأ في حال عدم وجوده return toast.error("Comment is required") } // تحويل تقييم المستخدم إلى رقم صحيح والتحقق من صحته const numericRate = parseInt(rate, 10); if (isNaN(numericRate) || numericRate < 1 || numericRate > 5) { return toast.error("Invalid rating value"); } // إرسال المراجعة باستخدام الدالة postReview dispatch(postReview(book._id, { rate: numericRate, comment })) }; return ( <div className={`modal ${showModal ? "show" : ""}`}> <div className="modal-content"> <span className="close" onClick={handleClose}>×</span> <h2>Submit Your Review</h2> <form onSubmit={submitReview}> <div className="rating-input"> <label>Rating:</label> <select value={rate} onChange={(e) => setRating(e.target.value)} required> <option value="" disabled>Select a rating</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> </select> </div> <div className="comment"> <label>Comment:</label> <textarea value={comment} onChange={(e) => setComment(e.target.value)} required /> </div> <button className='modal-btn' type="submit">Submit</button> </form> </div> </div> ); }; export default Modal; تحديث bookSlice لتضمين الدالة updateBook: const bookSlice = createSlice({ name: "book", initialState: { books: [], error: false, loading: false, }, reducers: { getBooks(state, action) { state.books = action.payload; }, findBook(state, action) { state.books = action.payload; }, addReviews(state, action) { state.books = action.payload; }, updateBook(state, action) { // البحث عن الكتاب المحدث وتحديثه const updatedBook = action.payload; const index = state.books.findIndex(book => book._id === updatedBook._id); if (index !== -1) { state.books[index] = updatedBook; } }, setLoading(state) { state.loading = true; }, clearLoading(state) { state.loading = false; }, setError(state) { state.error = true; }, clearError(state) { state.error = false; }, } }); export const bookActions = bookSlice.actions; export default bookSlice.reducer; 1 اقتباس
السؤال
محمود سعداوي2
السلام عليكم.
في المثال التالي، أواجه الأخطاء التالية:
لايتم إضافة التقييم إلى واجهة الصفحة إلا بعد التحديث
الكود
bookController
// method POST // route api/books/:id/reviews // desc Add a book review // access Private | auth const addReview = asyncHandler(async(req, res) => { const { id } = req.params const { comment, rate } = req.body const book = await Book.findById(id) const user = await User.findById(req.userId) if (!book) { return res.status(404).json({ message: "Book Not Found" }) } const isRated = book.reviews.findIndex(m => m.user == req.userId) if (isRated > -1){ return res.status(403).send({ message: "Review Is Already Added" }); } const totalRate = book.reviews.reduce((sum, review) => sum + review.rate ,0) const finalRate = (totalRate + rate) / (book.reviews.length + 1) await Book.updateOne( { _id: id } , { $push: { reviews: { user: req.userId, username: user.name, comment, rate } }, $set: { rate: finalRate } } ) res.status(201).json({ message: "Review added successfully" }) })
Frontend
apiCall
// Post Review export function postReview(bookId, review) { return async (dispatch, getState) => { try { dispatch(bookActions.setLoading()) const {data} = await axios.post(`${BOOK_URL}/${bookId}/reviews`, review, { headers: { "authorization": getState().auth.user.accessToken } }); toast.success(data?.message) dispatch(bookActions.addReviews()); dispatch(bookActions.clearLoading()); } catch (error) { toast.error(error?.response?.data.message); dispatch(bookActions.clearLoading()); } }; }
bookSlice
const bookSlice = createSlice({ name: "book", initialState: { books: [], error: false, loading: false, }, reducers: { getBooks(state, action) { state.books = action.payload; }, findBook(state, action) { state.books = action.payload; }, addReviews(state, action) { state.books = action.payload; }, setLoading(state) { state.loading = true; }, clearLoading(state) { state.loading = false; }, setError(state) { state.error = true; }, clearError(state) { state.error = false; }, } }
Component
شكرا على المساعدة
1 جواب على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.