اذهب إلى المحتوى

السؤال

نشر

عندي مشروع React + Express.js ورفعت مجلد خادم على render و تم رفعه بنجاح وعطاني رابط واستخدمته بدل من localhost:3000 

وبعدين حطيت رابط مشروع في cors بهذه شكل 

app.use(cors({
  origin: 'https://mern-image-gallery-app.netlify.app/', 
  credentials: true
}));

ورفعت مجلد عميل على Netlify وخادم لم يعمل.

Recommended Posts

  • 0
نشر

يجب حذف الشرطة المائلة (/) من النهاية فالمتصفحات ترسل ال Origin بدون شرطة مائلة في النهاية والكود لديك يحتوي عليها.

لذلك قم بإزالة / من نهاية الرابط:

app.use(cors({
  origin: 'https://mern-image-gallery-app.netlify.app',
  credentials: true
}));

وتأكد من أن الكود السابق في بداية الملف لديك أى قبل أى route موجود حتى يتم تنفيذه أولا .

وأخيرا بعد إجراء أي تعديل على ملف الخادم، يجب أن تقوم بإعادة نشره (re-deploy) على Render حتى يتم تطبيق التغييرات وتأكد من أن عملية النشر تمت بنجاح على Render.

  • 0
نشر

مشكلة لم تنحل هكذا استخدمته في axios 

import express from 'express';
import dotenv from 'dotenv';
import { connectDB } from './libs/connectDB.js';
import userRouter from './routes/user.route.js';
import imageRouter from './routes/image.route.js';
import cors from 'cors';
import path from 'path';
dotenv.config();
const app = express();
app.use(express.json())
app.use(cors({
  origin: 'https://mern-image-gallery-app.netlify.app', 
  credentials: true
}));
connectDB();
const port = process.env.PORT || 3000;

app.get('/' , (req , res) => {
    res.send("Hello World!");
});

app.use('/api/auth' ,userRouter);
app.use('/api/images' ,imageRouter);

app.use('/uploads', express.static(path.join(process.cwd(), 'public', 'uploads')));
app.listen(port , () => {
    console.log(`Server is running on port ${port}`)
});
import { useState, useEffect } from 'react';
import axios from 'axios';
import { FaHeart, FaRegHeart } from 'react-icons/fa';
import { useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';

const Home = () => {
  const [images, setImages] = useState([]);
  const [loading, setLoading] = useState(true);
  const [message, setMessage] = useState("");
  const [modalImage, setModalImage] = useState(null); 
  const navigate = useNavigate();
  const token = localStorage.getItem("token"); 

  useEffect(() => {
    const fetchImages = async () => {
      try {
        const res = await axios.get("https://mern-stack-image-gallery-app.onrender.com/api/images");
        setImages(res.data); 
      } catch (err) {
        console.error(err);
        setMessage("حدث خطأ أثناء جلب الصور");
      } finally {
        setLoading(false);
      }
    };
    fetchImages();
  }, []);

  const handleLike = async (id) => {
    if (!token) {
      toast.error("يجب تسجيل الدخول اولاُ", { duration: 3000 });
      navigate("/login"); 
      return;
    }

    try {
      const res = await axios.post(
        `https://mern-stack-image-gallery-app.onrender.com/api/images/like/${id}`,
        {},
        { headers: { Authorization: `Bearer ${token}` } }
      );

      setImages(images.map((img) =>
        img._id === id ? { ...img, likes: res.data.likes } : img
      ));

    } catch (error) {
      console.error(error);
      toast.error(error.response?.data?.message || "حدث خطأ أثناء الإعجاب بالصورة");
    }
  };

  if (loading) return <p className="text-center mt-10">جارٍ تحميل الصور...</p>;
  if (message) return <p className="text-center mt-10 text-red-500">{message}</p>;

  return (
    <div className="container mx-auto p-4 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
      {images.map((img) => (
        <div key={img._id} className="border rounded shadow p-2 bg-white relative h-72">
          <img
            src={`https://mern-stack-image-gallery-app.onrender.com${img.imageUrl}`}
            alt={img.title || "img"}
            className="w-full h-48 object-cover rounded cursor-pointer"
            onClick={() => setModalImage(img)} 
          />
          <h3 className=" mt-2 font-semibold">{img.title}</h3>
          <p className='text-gray-800'>{img.description}</p>
          <button
            onClick={() => handleLike(img._id)}
            className="absolute top-2 right-2 text-red-500 text-xl"
          >
            {img.likes && img.likes > 0 ? <FaHeart /> : <FaRegHeart />}
            <span className="ml-1">{img.likes || 0}</span>
          </button>
        </div>
      ))}

      
      {modalImage && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded p-4 max-w-lg w-full relative">
            <button
              onClick={() => setModalImage(null)}
              className="absolute top-2 right-2 text-xl font-bold text-gray-600 hover:text-black"
            >
              
            </button>
            <img
              src={`https://mern-stack-image-gallery-app.onrender.com${modalImage.imageUrl}`}
              alt={modalImage.title}
              className="w-full h-auto rounded mb-4"
            />
            <h2 className="text-xl font-bold mb-2">{modalImage.title}</h2>
            <p className="text-gray-700">{modalImage.description}</p>
          </div>
        </div>
      )}
    </div>
  );
};

export default Home;

 

  • 0
نشر
بتاريخ 16 دقائق مضت قال Zen Eddin Allaham:

مشكلة لم تنحل هكذا استخدمته في axios 

import express from 'express';
import dotenv from 'dotenv';
import { connectDB } from './libs/connectDB.js';
import userRouter from './routes/user.route.js';
import imageRouter from './routes/image.route.js';
import cors from 'cors';
import path from 'path';
dotenv.config();
const app = express();
app.use(express.json())
app.use(cors({
  origin: 'https://mern-image-gallery-app.netlify.app', 
  credentials: true
}));
connectDB();
const port = process.env.PORT || 3000;

app.get('/' , (req , res) => {
    res.send("Hello World!");
});

app.use('/api/auth' ,userRouter);
app.use('/api/images' ,imageRouter);

app.use('/uploads', express.static(path.join(process.cwd(), 'public', 'uploads')));
app.listen(port , () => {
    console.log(`Server is running on port ${port}`)
});
import { useState, useEffect } from 'react';
import axios from 'axios';
import { FaHeart, FaRegHeart } from 'react-icons/fa';
import { useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';

const Home = () => {
  const [images, setImages] = useState([]);
  const [loading, setLoading] = useState(true);
  const [message, setMessage] = useState("");
  const [modalImage, setModalImage] = useState(null); 
  const navigate = useNavigate();
  const token = localStorage.getItem("token"); 

  useEffect(() => {
    const fetchImages = async () => {
      try {
        const res = await axios.get("https://mern-stack-image-gallery-app.onrender.com/api/images");
        setImages(res.data); 
      } catch (err) {
        console.error(err);
        setMessage("حدث خطأ أثناء جلب الصور");
      } finally {
        setLoading(false);
      }
    };
    fetchImages();
  }, []);

  const handleLike = async (id) => {
    if (!token) {
      toast.error("يجب تسجيل الدخول اولاُ", { duration: 3000 });
      navigate("/login"); 
      return;
    }

    try {
      const res = await axios.post(
        `https://mern-stack-image-gallery-app.onrender.com/api/images/like/${id}`,
        {},
        { headers: { Authorization: `Bearer ${token}` } }
      );

      setImages(images.map((img) =>
        img._id === id ? { ...img, likes: res.data.likes } : img
      ));

    } catch (error) {
      console.error(error);
      toast.error(error.response?.data?.message || "حدث خطأ أثناء الإعجاب بالصورة");
    }
  };

  if (loading) return <p className="text-center mt-10">جارٍ تحميل الصور...</p>;
  if (message) return <p className="text-center mt-10 text-red-500">{message}</p>;

  return (
    <div className="container mx-auto p-4 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
      {images.map((img) => (
        <div key={img._id} className="border rounded shadow p-2 bg-white relative h-72">
          <img
            src={`https://mern-stack-image-gallery-app.onrender.com${img.imageUrl}`}
            alt={img.title || "img"}
            className="w-full h-48 object-cover rounded cursor-pointer"
            onClick={() => setModalImage(img)} 
          />
          <h3 className=" mt-2 font-semibold">{img.title}</h3>
          <p className='text-gray-800'>{img.description}</p>
          <button
            onClick={() => handleLike(img._id)}
            className="absolute top-2 right-2 text-red-500 text-xl"
          >
            {img.likes && img.likes > 0 ? <FaHeart /> : <FaRegHeart />}
            <span className="ml-1">{img.likes || 0}</span>
          </button>
        </div>
      ))}

      
      {modalImage && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded p-4 max-w-lg w-full relative">
            <button
              onClick={() => setModalImage(null)}
              className="absolute top-2 right-2 text-xl font-bold text-gray-600 hover:text-black"
            >
              
            </button>
            <img
              src={`https://mern-stack-image-gallery-app.onrender.com${modalImage.imageUrl}`}
              alt={modalImage.title}
              className="w-full h-auto rounded mb-4"
            />
            <h2 className="text-xl font-bold mb-2">{modalImage.title}</h2>
            <p className="text-gray-700">{modalImage.description}</p>
          </div>
        </div>
      )}
    </div>
  );
};

export default Home;

 

هناك خطأ شائع يحدث عندما نستخدم credentials: true عندما تضبط الخادم (Express) ليقبل credentials: true فأنت تخبر المتصفح أنك تثق في هذا الموقع  لدرجة أنك تسمح له بإرسال واستقبال الكوكيز أو التوكنز (headers) الخاصة بالمصادقة.

وفي المقابل يجب على العميل (React/Axios) أن يرسل withCredentials: true مع كل طلب وبدون تلك الخطوة سيرفض المتصفح إرسال الطلب كإجراء أمني.

لذلك أولا في الخادم يجب ترتيب الـ Middlewares قم بجعل ال cors هو أول middleware يتم استخدامه حتى قبل express.json() وهذا يضمن أن الطلبات يتم معالجتها بشكل صحيح.

بعد ذلك في الواجهة الأمامية أضف withCredentials: true إلى جميع طلبات axios الخاصة بك :

useEffect(() => {
    const fetchImages = async () => {
      try {
        const res = await axios.get(
          "https://mern-stack-image-gallery-app.onrender.com/api/images",
          { withCredentials: true } // أضف هذا
        );
        setImages(res.data); 
      } catch (err) {
        // ...
      } finally {
        // ...
      }
    };
    fetchImages();
  }, []);

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...