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

السؤال

نشر

السلام عليكم.

أريد تغيير  لون زر الإعجاب عند النقر.

إذا كان المعجبين الحاليين بالعنصر يحتوي معرف المستخدم يقع تغيير اللون للأحمر. عند النقر في المرة الثانية يقع حذف المستخدم من قائمة المعجبين و يعود اللون لحاله الأول.

في الكود التالي توصلت إلى تحديد عدد المعجبين لكن أواجه مشكل في تغيير اللون عند الإعجاب.

الكود

/**
   * HandleLike An Image
   */
const handleLikeImage = async (id) => {
    if (!user) {
      navigate("/login");
      return;
    }

    await axios
      .put(`/api/images/like/${id}`, like, {
        headers: {
          "Content-Type": "application/json",
          "x-auth-token": user.data.token,
        },
      })
      .then((res) => {
        setLike(res.data);
        setNumLikes(res.data.likes.length);
        handleLikedColor()
        // setKey(id)
      })
      .catch((err) => {
        setError(err.response.data.msg);
        setTimeout(() => {
          setError(null);
        }, 1500);
      });
  };
 ********************
/**
   * Handle Change Icon Color
   */
  const handleLikedColor = (id) => {
    const isLiked = likes.filter((item) => item.user === userId);
    if (isLiked.length > 0) {
      setLikedColor(true);
    } else {
      setLikedColor(false)
      
    }
  };
  
  useEffect(() => {
    handleLikedColor();
  }, [likes, userId]);
******
<div className="menu-like">
        <div
          className={likedColor ? "like isLike" : "like"}
          onClick={() => {
            handleLikeImage(imageId);
            // console.log(key)
          }}
        >
          <i className="fa-regular fa-thumbs-up"></i>
        </div>
        {numLikes === 0 ? "" : <div className="dislike">{numLikes}</div>}
      </div>

شكرا على المساعدة

Recommended Posts

  • 0
نشر

أنت تقوم بفحص إذا كان المستخدم قد قام بالإعجاب بالصورة أم لا، وتقوم بتحديث اللون بناءًا على ذلك، لذا هناك بعض الأمور من الأفضل القيام بها لتحسين الكود كالتالي:

1- إضافة متغير محلي لتتبع حالة اللون بدلاً من استخدام likedColor كحالة عامة، وسيساعد ذلك في تجنب المشاكل المحتملة مع تحديث حالة اللون بشكل صحيح.

// داخل الكومبوننت
const [buttonColor, setButtonColor] = useState(false);

// ...

const handleLikedColor = () => {
  const isLiked = likes.filter((item) => item.user === userId);
  setButtonColor(isLiked.length > 0);
};

useEffect(() => {
  handleLikedColor();
}, [likes, userId]);

2- حاول تحديث لون الزر في مكان واحد فقط، في داخل handleLikeImage بدلاً من استدعاء handleLikedColor بشكل منفصل.

const handleLikeImage = async (id) => {
  // ...

  await axios
    .put(`/api/images/like/${id}`, like, {
      headers: {
        "Content-Type": "application/json",
        "x-auth-token": user.data.token,
      },
    })
    .then((res) => {
      setLike(res.data);
      setNumLikes(res.data.likes.length);
      setButtonColor(res.data.likes.some((item) => item.user === userId));
    })
    .catch((err) => {
      // ...
    });
};

3- استخدم الحالة المحلية (buttonColor) مباشرة في الرندر بدلاً من likedColor.

<div className="menu-like">
  <div
    className={buttonColor ? "like isLike" : "like"}
    onClick={() => {
      handleLikeImage(imageId);
    }}
  >
    <i className="fa-regular fa-thumbs-up"></i>
  </div>
  {numLikes === 0 ? "" : <div className="dislike">{numLikes}</div>}
</div>

 

  • 0
نشر

يبدو من الكود الذي شاركته ان المنطق صحيح، ولكن هل يمكنك طباعة الـ isLiked في الوظيفة handleLikedColor فقد تكون المشكلة من هنا (likes لا يتم تحديثها).

هل يمكنك مشاركة كامل الكود حتى استطيع مساعدتك بشكل افضل؟!

  • 0
نشر
بتاريخ 1 دقيقة مضت قال عمر قره محمد:

يبدو من الكود الذي شاركته ان المنطق صحيح، ولكن هل يمكنك طباعة الـ isLiked في الوظيفة handleLikedColor فقد تكون المشكلة من هنا (likes لا يتم تحديثها).

هل يمكنك مشاركة كامل الكود حتى استطيع مساعدتك بشكل افضل؟!

تفضل

import React, { useState, useEffect } from "react";
import './views.css'
import { Link, useNavigate, useParams } from 'react-router-dom';
import moment from 'moment'
import axios from "axios";
import Alert from "../alert/Alert";
import defaultUser from "../../assets/photaty/avatar-profile.png"

function ImageCard(props) {
  const navigate = useNavigate();
  const [error, setError] = useState("");
  const [like, setLike] = useState([]);
  const {
    photo,
    title,
    author,
    createdAt,
    avatar,
    imageId,
    likes,
    edit_remove,
    handleRemove,
    userId,
  } = props;
  const user = JSON.parse(localStorage.getItem("user"));
  const imgSrc = photo && require(`../../assets/images/${photo}`);
  const avatarSrc = avatar
    ? require(`../../assets/profile/${avatar}`)
    : defaultUser;
  const [numLikes, setNumLikes] = useState(likes?.length);
  const [likedColor, setLikedColor] = useState(false);
  const [key, setKey] = useState(null);

  /**
   * HandleLike An Image
   */
  const handleLikeImage = async (id) => {
    if (!user) {
      navigate("/login");
      return;
    }

    await axios
      .put(`/api/images/like/${id}`, like, {
        headers: {
          "Content-Type": "application/json",
          "x-auth-token": user.data.token,
        },
      })
      .then((res) => {
        setLike(res.data);
        setNumLikes(res.data.likes.length);
        handleLikedColor()
        // setKey(id)
      })
      .catch((err) => {
        setError(err.response.data.msg);
        setTimeout(() => {
          setError(null);
        }, 1500);
      });
  };
  // console.log(likes)
  /**
   * Handle Change Icon Color
   */
  const handleLikedColor = (id) => {
    const isLiked = likes.filter((item) => item.user === userId);
    if (isLiked.length > 0) {
      setLikedColor(true);
    } else {
      setLikedColor(false)
      
    }
  };
  
  useEffect(() => {
    handleLikedColor();
  }, [likes, userId]);
  return (
    <div className="menu">
      {edit_remove ? (
        <>
          <div className="delete change" onClick={() => handleRemove(imageId)}>
            <i className="fa-solid fa-trash"></i>
          </div>
          <div className="edit change">
            <Link to={`/edit-photo/${imageId}`}>
              <i className="fa-solid fa-pen-to-square"></i>
            </Link>
          </div>
        </>
      ) : (
        ""
      )}
      <div className="menu-img">
        <img src={imgSrc} alt={`${title}`} className="img" />
        <span className="read-more">
          <Link to={`/${imageId}`}>
            <i className="fa-regular fa-square-plus"></i>
          </Link>
        </span>
      </div>
      <div className="menu-description">
        <img src={avatarSrc} alt="avatar" className="avatar" />
        <div className="menu-info">
          <h3 className="title">{title}</h3>
          <p className="date">
            created by: <span>{author}</span> at:
            <span>{moment(createdAt).format("DD-MM-YYYY")}</span>
          </p>
        </div>
      </div>

      <div className="menu-like">
        <div
          className={likedColor ? "like isLike" : "like"}
          onClick={() => {
            handleLikeImage(imageId);
            // console.log(key)
          }}
        >
          <i className="fa-regular fa-thumbs-up"></i>
        </div>
        {numLikes === 0 ? "" : <div className="dislike">{numLikes}</div>}
      </div>
    </div>
  );
}

export default ImageCard

 

بتاريخ 9 دقائق مضت قال Mustafa Suleiman:

أنت تقوم بفحص إذا كان المستخدم قد قام بالإعجاب بالصورة أم لا، وتقوم بتحديث اللون بناءًا على ذلك، لذا هناك بعض الأمور من الأفضل القيام بها لتحسين الكود كالتالي:

1- إضافة متغير محلي لتتبع حالة اللون بدلاً من استخدام likedColor كحالة عامة، وسيساعد ذلك في تجنب المشاكل المحتملة مع تحديث حالة اللون بشكل صحيح.

// داخل الكومبوننت
const [buttonColor, setButtonColor] = useState(false);

// ...

const handleLikedColor = () => {
  const isLiked = likes.filter((item) => item.user === userId);
  setButtonColor(isLiked.length > 0);
};

useEffect(() => {
  handleLikedColor();
}, [likes, userId]);

2- حاول تحديث لون الزر في مكان واحد فقط، في داخل handleLikeImage بدلاً من استدعاء handleLikedColor بشكل منفصل.

const handleLikeImage = async (id) => {
  // ...

  await axios
    .put(`/api/images/like/${id}`, like, {
      headers: {
        "Content-Type": "application/json",
        "x-auth-token": user.data.token,
      },
    })
    .then((res) => {
      setLike(res.data);
      setNumLikes(res.data.likes.length);
      setButtonColor(res.data.likes.some((item) => item.user === userId));
    })
    .catch((err) => {
      // ...
    });
};

3- استخدم الحالة المحلية (buttonColor) مباشرة في الرندر بدلاً من likedColor.

<div className="menu-like">
  <div
    className={buttonColor ? "like isLike" : "like"}
    onClick={() => {
      handleLikeImage(imageId);
    }}
  >
    <i className="fa-regular fa-thumbs-up"></i>
  </div>
  {numLikes === 0 ? "" : <div className="dislike">{numLikes}</div>}
</div>

 

لدي أربع عناصر.

في الأولين لم ينجح الكود. أما في البقية فقد نجح الكود.

  • 0
نشر
بتاريخ 37 دقائق مضت قال محمود سعداوي2:

تفضل

import React, { useState, useEffect } from "react";
import './views.css'
import { Link, useNavigate, useParams } from 'react-router-dom';
import moment from 'moment'
import axios from "axios";
import Alert from "../alert/Alert";
import defaultUser from "../../assets/photaty/avatar-profile.png"

function ImageCard(props) {
  const navigate = useNavigate();
  const [error, setError] = useState("");
  const [like, setLike] = useState([]);
  const {
    photo,
    title,
    author,
    createdAt,
    avatar,
    imageId,
    likes,
    edit_remove,
    handleRemove,
    userId,
  } = props;
  const user = JSON.parse(localStorage.getItem("user"));
  const imgSrc = photo && require(`../../assets/images/${photo}`);
  const avatarSrc = avatar
    ? require(`../../assets/profile/${avatar}`)
    : defaultUser;
  const [numLikes, setNumLikes] = useState(likes?.length);
  const [likedColor, setLikedColor] = useState(false);
  const [key, setKey] = useState(null);

  /**
   * HandleLike An Image
   */
  const handleLikeImage = async (id) => {
    if (!user) {
      navigate("/login");
      return;
    }

    await axios
      .put(`/api/images/like/${id}`, like, {
        headers: {
          "Content-Type": "application/json",
          "x-auth-token": user.data.token,
        },
      })
      .then((res) => {
        setLike(res.data);
        setNumLikes(res.data.likes.length);
        handleLikedColor()
        // setKey(id)
      })
      .catch((err) => {
        setError(err.response.data.msg);
        setTimeout(() => {
          setError(null);
        }, 1500);
      });
  };
  // console.log(likes)
  /**
   * Handle Change Icon Color
   */
  const handleLikedColor = (id) => {
    const isLiked = likes.filter((item) => item.user === userId);
    if (isLiked.length > 0) {
      setLikedColor(true);
    } else {
      setLikedColor(false)
      
    }
  };
  
  useEffect(() => {
    handleLikedColor();
  }, [likes, userId]);
  return (
    <div className="menu">
      {edit_remove ? (
        <>
          <div className="delete change" onClick={() => handleRemove(imageId)}>
            <i className="fa-solid fa-trash"></i>
          </div>
          <div className="edit change">
            <Link to={`/edit-photo/${imageId}`}>
              <i className="fa-solid fa-pen-to-square"></i>
            </Link>
          </div>
        </>
      ) : (
        ""
      )}
      <div className="menu-img">
        <img src={imgSrc} alt={`${title}`} className="img" />
        <span className="read-more">
          <Link to={`/${imageId}`}>
            <i className="fa-regular fa-square-plus"></i>
          </Link>
        </span>
      </div>
      <div className="menu-description">
        <img src={avatarSrc} alt="avatar" className="avatar" />
        <div className="menu-info">
          <h3 className="title">{title}</h3>
          <p className="date">
            created by: <span>{author}</span> at:
            <span>{moment(createdAt).format("DD-MM-YYYY")}</span>
          </p>
        </div>
      </div>

      <div className="menu-like">
        <div
          className={likedColor ? "like isLike" : "like"}
          onClick={() => {
            handleLikeImage(imageId);
            // console.log(key)
          }}
        >
          <i className="fa-regular fa-thumbs-up"></i>
        </div>
        {numLikes === 0 ? "" : <div className="dislike">{numLikes}</div>}
      </div>
    </div>
  );
}

export default ImageCard

 

لدي أربع عناصر.

في الأولين لم ينجح الكود. أما في البقية فقد نجح الكود.

لا يبدو ان المشكلة من المنطق ولكن يبدو انها من الـ likes أو من الربط مع الـ api.

هل يمكنك تجريب اضافة الكود التالي واخباري بالنتيجة التي تحصل عليها عند اضافة لايك وعند حذفه ؟!

const handleLikedColor = (id) => {
	const isLiked = likes.filter((item) => item.user === userId);
	console.log({ "isLiked.length > 0": isLiked.length > 0, likes, userId, isLiked });
	if (isLiked.length > 0) {
		setLikedColor(true);
	} else {
		setLikedColor(false)
	}
};

إن كان بإمكانك مشاركة كامل مجلد المشروح حتى استطيع التجريب ومساعدتك بشكل افضل.

  • 0
نشر
بتاريخ 39 دقائق مضت قال عمر قره محمد:

لا يبدو ان المشكلة من المنطق ولكن يبدو انها من الـ likes أو من الربط مع الـ api.

هل يمكنك تجريب اضافة الكود التالي واخباري بالنتيجة التي تحصل عليها عند اضافة لايك وعند حذفه ؟!

const handleLikedColor = (id) => {
	const isLiked = likes.filter((item) => item.user === userId);
	console.log({ "isLiked.length > 0": isLiked.length > 0, likes, userId, isLiked });
	if (isLiked.length > 0) {
		setLikedColor(true);
	} else {
		setLikedColor(false)
	}
};

إن كان بإمكانك مشاركة كامل مجلد المشروح حتى استطيع التجريب ومساعدتك بشكل افضل.

أعتقد أن النتيجة صحيحة و لا تحتوي أخطاء


{isLiked.length > 0: false, likes: Array(2), userId: '654b804c1157c8dc408a4aec', isLiked: Array(0)}
isLiked
: 
[]
isLiked.length > 0
: 
false
likes
: 
Array(2)
0
: 
{user: '654aabf3aab1f445eab9faf1', _id: '6552486f570a319a6442a77b'}
1
: 
{user: '654bef88849d21ff857fb57f', _id: '654bf1f2849d21ff857fb726'}
length
: 
2
[[Prototype]]
: 
Array(0)
userId
: 
"654b804c1157c8dc408a4aec"
[[Prototype]]
: 
Object
ImageCard.jsx:65 
{isLiked.length > 0: true, likes: Array(1), userId: '654b804c1157c8dc408a4aec', isLiked: Array(1)}
isLiked
: 
Array(1)
0
: 
{user: '654b804c1157c8dc408a4aec', _id: '654be81ff7cc95c50a0e74fe'}
length
: 
1
[[Prototype]]
: 
Array(0)
isLiked.length > 0
: 
true
likes
: 
Array(1)
0
: 
{user: '654b804c1157c8dc408a4aec', _id: '654be81ff7cc95c50a0e74fe'}
length
: 
1
[[Prototype]]
: 
Array(0)
userId
: 
"654b804c1157c8dc408a4aec"
[[Prototype]]
: 
Object
ImageCard.jsx:65 
{isLiked.length > 0: false, likes: Array(2), userId: '654aabf3aab1f445eab9faf1', isLiked: Array(0)}
isLiked
: 
[]
isLiked.length > 0
: 
false
likes
: 
Array(2)
0
: 
{user: '654cab8448ef64412386c076', _id: '654cace048ef64412386c0cf'}
1
: 
{user: '654bef88849d21ff857fb57f', _id: '654bf207849d21ff857fb74c'}
length
: 
2
[[Prototype]]
: 
Array(0)
userId
: 
"654aabf3aab1f445eab9faf1"
[[Prototype]]
: 
Object
ImageCard.jsx:65 
{isLiked.length > 0: false, likes: Array(0), userId: '654aabf3aab1f445eab9faf1', isLiked: Array(0)}
isLiked
: 
[]
isLiked.length > 0
: 
false
likes
: 
[]
userId
: 
"654aabf3aab1f445eab9faf1"
[[Prototype]]
: 
Object

تفضل ملفات المشروع

hsoub.zip

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...