React JS and API express Server (MERN) regarding the Metadata that pass for the Social Media get nothing after build for Production

35 views Asked by At

I'm using MERN stack and building production for the website server but the meta is captured from my index.js only. I'm using REACT-HELMET for each and every page but the metadata,it does not capture. I have read a lot of articles that say SSR and CSR

I'm not sure MERN belongs to which one. cause I am using express for API is SSR or CSR? I'm a bit confused.

and how could I make my share link from a subpage e.g:www.test.com/product/x123123*id (mapping data from API server) e.g. product Catfood, title and image can be showing displayed on Social like Facebook metadata: og:image and the title will change accordingly.

i have tested react-snap but it does not work.

import React, { useEffect, useState } from 'react';
import {
    addViewAction,
    getlistingAction,
    likeListingAction,
    unLikeListingAction,
} from '../../redux/slices/listingSlices';
import { getUserProfileAction } from '../../redux/slices/userSlices';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import ErrorMsg from '../../components/ErrorMsg/ErrorMsg';
import LoadingComponent from '../../components/LoadingComponent/loadingComponent';
import ReactImageGallery from 'react-image-gallery';
import 'react-image-gallery/styles/css/image-gallery.css';
import BackButton from '../../components/Backbutton';
import {
    FaBed,
    FaRulerCombined,
    FaBath,
    FaRegHeart,
    FaHeart,
    FaFacebook,
    FaWhatsapp,
    FaEnvelope,
    FaViber,
    FaTwitter,
    FaLine,
    FaTelegram,
    FaShareAlt,
    FaPhone,
    FaMap,
    FaMailBulk,
    FaEye,
} from 'react-icons/fa';
import { LuLampFloor } from 'react-icons/lu';
import SuccesMsg from '../../components/SuccessMsg/SuccessMsg';
import MortgageCalculator from '../../components/MorgageCalculator';
import {
    FacebookShareButton,
    EmailShareButton,
    ViberShareButton,
    TwitterShareButton,
    LineShareButton,
    TelegramShareButton,
    WhatsappShareButton,
} from 'react-share';
import ReactPlayer from 'react-player';
import { Helmet } from 'react-helmet';

const ListingDetails = ({ color }) => {
    const [myProfile, setMyProfile] = useState(null);
    const [myListing, setMyListing] = useState(null);
    const [isLiked, setIsLiked] = useState(false);
    const [coordinates, setCoordinates] = useState([]);
    const [showShareTooltip, setShowShareTooltip] = useState(false);

    const dispatch = useDispatch();
    const params = useParams();
    const listingId = params.id;

    // eslint-disable-next-line
    const { listing, error, loading, success } = useSelector(
        (state) => state?.listing
    );

    useEffect(() => {
        const fetchData = async () => {
            try {
                await dispatch(addViewAction(listingId));
                const listingResponse = await dispatch(getlistingAction(listingId));
                const listing = listingResponse.payload.listing;
                setMyListing(listing);
                await setCoordinates([listing.coordinateX, listing.coordinateY]);

                // Fetch user profile after fetching the listing
                const profileResponse = await dispatch(getUserProfileAction());
                setMyProfile(profileResponse.payload.myProfile);

                // Fetch liked status after fetching user profile
                const likedUsers = listing?.likes;
                const hasLike = likedUsers?.some((userIds) =>
                    userIds.includes(myProfile?._id)
                );
                setIsLiked(hasLike);
            } catch (error) {
                console.error('Error fetching data:', error);
            }
        };

        if (!myListing) {
            fetchData();
        }
    }, [dispatch, listingId, myListing, myProfile]);

    const refreshListing = async () => {
        try {
            const response = await dispatch(getlistingAction(listingId));
            setMyListing(response.payload.listing);
        } catch (error) {
            console.error('Error refreshing listing:', error);
        }
    };

    const likeListingHandler = async () => {
        try {
            await dispatch(likeListingAction(listingId));
            refreshListing();
        } catch (error) {
            console.error('Error liking listing:', error);
        }
    };

    const unListingHandler = async () => {
        try {
            await dispatch(unLikeListingAction(listingId));
            refreshListing();
        } catch (error) {
            console.error('Error unliking listing:', error);
        }
    };

    if (loading || !myListing) {
        return <LoadingComponent />;
    }

    if (error) {
        return <ErrorMsg message={error} />;
    }

    const homevalue = myListing ? myListing.price : 0; // Replace 0 with a default value if needed
    const downpayment = (homevalue * 10) / 100; //

    const images = myListing.images.map((image, index) => ({
        original: image,
        description: `Photo ${index + 1}`,
    }));

    // Assuming myListing.description contains the property description text
    const description = myListing.description;

    // Replace newline characters with <br> tags
    const formattedDescription = description.replace(/\n/g, '<br>');

    const openGoogleMapInNewWindow = (coordinates) => {
        // Define the URL for the new window with coordinates as a query parameter
        const url = `/google-map?lat=${coordinates[0]}&lng=${coordinates[1]}`;
        const newWindow = window.open(url, '_blank', 'width=800,height=600');

        // Handle any pop-up blocker issues
        if (!newWindow) {
            alert('Please allow pop-ups to open the map.');
        }
    };

    //============================================================================================================================
    //====================================================BELOW is RETURN ========================================================
    //============================================================================================================================

    return (
        <div className="dark:bg-gray-900">
            <Helmet>
                <title>{myListing.title}</title>
                <meta property="og:title" content={myListing.title} />
                <meta property="og:image" content={myListing.images[0]} />
                <meta property="og:type" content="website" />
            </Helmet>
            <div className="container mx-auto bg-gray-100 dark:bg-gray-900 h-full ">
                <div className="flex justify-start py-4 pl-5">
                    <BackButton />
                </div>
                <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 bg-gray-100 dark:bg-gray-900 p- h-full pt-5">
                    <div className="">
                        <div className="flex">
                            <ReactImageGallery items={images} />
                        </div>
                        {myListing.videoURL ? (
                            <div className="flex justify-center align-middle p-2 lg:py-16">
                                <ReactPlayer url={myListing.videoURL} />
                            </div>
                        ) : null}
                    </div>

                    <div className="container p-2 mx-auto">
                        <div className="w-auto rounded-xl overflow-hidden shadow-lg dark:bg-gray-800 p-5 text-gray-600">
                            <div className="p-3">
                                <div className="font-bold text-xl mb-2 dark:text-gray-300">
                                    For {myListing.propertyType}
                                </div>
                                <div className="font-bold text-xl mb-2 dark:text-gray-300">
                                    {myListing.title}
                                </div>
                                <div className="mb-2 dark:text-gray-500">
                                    {myListing.address}
                                </div>
                                <div className="grid grid-cols-3 gap-4 text-center">
                                    {myProfile ? (
                                        !isLiked ? (
                                            <button
                                                onClick={likeListingHandler}
                                                className="flex items-center gap-1 m-2 text-2xl text-gray-400"
                                            >
                                                <FaRegHeart />
                                            </button>
                                        ) : (
                                            <button
                                                onClick={unListingHandler}
                                                className="flex items-center gap-1 m-2 text-2xl text-gray-400"
                                            >
                                                <FaHeart className="text-red-700" />
                                            </button>
                                        )
                                    ) : null}{' '}
                                    <div className="p-2">
                                        <button
                                            onClick={() => openGoogleMapInNewWindow(coordinates)}
                                            className="text-2xl text-gray-400 focus:outline-none"
                                        >
                                            <FaMap />
                                        </button>
                                    </div>
                                    <div className="p-2">
                                        <button
                                            type="button"
                                            className="text-2xl text-gray-400 focus:outline-none"
                                            onClick={() => setShowShareTooltip(!showShareTooltip)}
                                        >
                                            <FaShareAlt />
                                        </button>

                                        {showShareTooltip && (
                                            <div className="absolute z-10 mt-2 -ml-2 transform -translate-x-1/2 w-36 p-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
                                                <div className="py-1 text-start">
                                                    <FacebookShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaFacebook className="text-xl mr-2" />
                                                            Facebook
                                                        </div>
                                                    </FacebookShareButton>
                                                    <WhatsappShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaWhatsapp className="text-xl mr-2" />
                                                            WhatsApp
                                                        </div>
                                                    </WhatsappShareButton>
                                                    <EmailShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaEnvelope className="text-xl mr-2" />
                                                            Email
                                                        </div>
                                                    </EmailShareButton>
                                                    <ViberShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaViber className="text-xl mr-2" />
                                                            Viber
                                                        </div>
                                                    </ViberShareButton>
                                                    <TwitterShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaTwitter className="text-xl mr-2" />
                                                            Twitter
                                                        </div>
                                                    </TwitterShareButton>
                                                    <LineShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaLine className="text-xl mr-2" />
                                                            Line
                                                        </div>
                                                    </LineShareButton>
                                                    <TelegramShareButton url={window.location.href}>
                                                        <div className="flex items-center">
                                                            <FaTelegram className="text-xl mr-2" />
                                                            Telegram
                                                        </div>
                                                    </TelegramShareButton>
                                                    {/* Add more social media share buttons here */}
                                                </div>
                                            </div>
                                        )}
                                    </div>
                                </div>

                                <div className="grid grid-cols-2 gap-1 px-1 py-3 text-gray-500 dark:text-gray-300">
                                    <div className="flex items-center text-xl">
                                        <FaBed className="mr-2" /> {myListing.beds} Room
                                    </div>
                                    <div className="flex items-center text-xl">
                                        <FaRulerCombined className="mr-2" /> {myListing.sqfeet} Sqft
                                    </div>
                                    <div className="flex items-center text-xl">
                                        <FaBath className="mr-2" /> {myListing.bathroom} Bath
                                    </div>
                                    <div className="flex items-center text-xl">
                                        <LuLampFloor className="mr-2" /> {myListing.furnishing}
                                    </div>
                                </div>
                            </div>
                            <hr />
                            <div className="p-2">
                                {!myListing.propertyType === 'buy' ? (
                                    <div className="font-bold text-xl mb-2 dark:text-gray-300">
                                        Price: {myListing.price} / month
                                    </div>
                                ) : (
                                    <div className="font-bold text-xl mb-2 dark:text-gray-300">
                                        RM {myListing.price.toLocaleString()}
                                        {myListing.propertyType !== 'Rent' ? null : '/ Month'}
                                    </div>
                                )}
                            </div>
                            <div className="p-2">
                                <div className="mb-2 dark:text-gray-300">
                                    RM {myListing.psf} Per Sqft
                                </div>
                                <div className="mb-2 dark:text-gray-300">
                                    {myListing.psf > 43560
                                        ? `${myListing.psf / 43560} Acres`
                                        : `${myListing.psf} Sqft`}
                                </div>
                            </div>

                            <div className="dark:text-gray-300 p-5 col-span-2">
                                <hr />
                                <label className="font-bold">Unit Features</label>
                                <hr />
                                <div className="overflow-auto max-h-40">
                                    {' '}
                                    {/* Add a max-height and overflow property */}
                                    {myListing.unitFeatures}
                                </div>
                            </div>

                            <div className="dark:text-gray-300 p-5 col-span-2">
                                <hr />
                                <label className="font-bold">Facilities</label>
                                <hr />
                                <div className="overflow-auto max-h-40">
                                    {' '}
                                    {/* Add a max-height and overflow property */}
                                    {myListing.facilities}
                                </div>
                            </div>
                            <div className="font-bold text-xl mb-2 dark:text-gray-300 p-3">
                                About This Property <br />
                                <br />
                                <p
                                    className="text-sm font-lite"
                                    dangerouslySetInnerHTML={{ __html: formattedDescription }}
                                ></p>
                            </div>

                            <div className="grid grid-cols-2 gap-4">
                                <div className="text-lg font-bold flex items-center">
                                    <FaEye className="mr-3" />
                                    {myListing.numViews}
                                </div>
                            </div>
                            <div className="pt-4 pb-2 grid grid-cols-3 gap-2 text-center">
                                <a
                                    href={`https://wa.me/${encodeURIComponent(
                                        myListing.user.whatsapp
                                    )}/?text=I%20am%20interested%20in%20${encodeURIComponent(
                                        myListing.title
                                    )}.%20Please%20provide%20me%20more%20information.`}
                                    className="flex flex-col items-center text-gray-800 dark:text-gray-100 bg-gray-200 dark:bg-gray-900 p-3 py-2 rounded-xl text-center"
                                    target="_blank"
                                    rel="noopener noreferrer"
                                >
                                    <FaWhatsapp className="text-2xl mb-1" />
                                    <p className="text-sm">Whatsapp</p>
                                </a>

                                <button
                                    onClick={() =>
                                        (window.location = `mailto:${myListing.user.email}`)
                                    }
                                    className="flex flex-col items-center text-gray-800 dark:text-gray-100 bg-gray-200 dark:bg-gray-900 p-3 py-2 rounded-xl"
                                >
                                    <FaMailBulk className="text-2xl mb-1" />
                                    <p className="text-sm">Email</p>
                                </button>

                                <a
                                    href={`tel:+${myListing.user.contactNumber}`}
                                    className="flex flex-col items-center text-gray-800 dark:text-gray-100 bg-gray-200 dark:bg-gray-900 p-3 py-2 rounded-xl"
                                >
                                    <FaPhone className="text-2xl mb-1" />
                                    <p className="text-sm">Call</p>
                                </a>
                            </div>
                        </div>
                        {success && <SuccesMsg message="Successfully Load" />}
                    </div>
                </div>

                <div className="p-5 lg:p-10">
                    {myListing.propertyType === 'Sale' ? (
                        <MortgageCalculator
                            homevalue={homevalue}
                            downpayment={downpayment}
                        />
                    ) : null}
                </div>
            </div>
        </div>
    );
};

export default ListingDetails;
0

There are 0 answers