v2.5.2
Giriş yap

React ile useEffect sürekli veri güncelleme nasıl yapılır?

uygar
362 defa görüntülendi

Arkadaşlar böyle bir kodum var, getElapsedTime fonksiyonunun sürekli güncellenmesini istiyorum.

useEffect içerisinde setInterval kullanmama rağmen, sayfa ilk load oluşunda saniyeyi ekliyor sonrasında kalıyor.

Yani bir daha çalışmıyor o fonksiyon. Bu duruma yardımcı olabilecek birisi var mı? Şimdiden teşekkür ederim.

Kodlar:

import {useMemo, useEffect} from 'react';
import {useLanyardWS} from 'use-lanyard';
import {AiOutlineLoading3Quarters} from "react-icons/ai";
import {FaSpotify} from "react-icons/fa";

const DiscordStatus = {
    online: 'Online',
    idle: 'Idle',
    dnd: 'Does not disturb',
    offline: 'Offline',
};

const StatusColor = {
    online: 'bg-online',
    idle: 'bg-idle',
    dnd: 'bg-dnd',
    offline: 'bg-offline',
};

const getAssetUrl = (appId: string, asset: string) =>
    asset.startsWith('mp:external')
        ? `https://media.discordapp.net/${asset.replace('mp:', '')}`
        : `https://cdn.discordapp.com/app-assets/${appId}/${asset}.png`;

const getElapsedTime = (timestamp: number) => {
    const elapsed = Date.now() - timestamp;
    const seconds = Math.floor(elapsed / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);
    const days = Math.floor(hours / 24);

    return `${days}d ${hours % 24}h ${minutes % 60}m ${seconds % 60}s`;
}

function Listening() {
    const presence = useLanyardWS('936597404055142470');

    // get Current time in timestamp format
    const getCurrentTime = () => {
        const date = new Date();
        return date.getTime();
    }

    const user = useMemo(() => {
        return presence?.discord_user;
    }, [presence]);

    const status = useMemo(() => {
        return presence && DiscordStatus[presence.discord_status as keyof typeof DiscordStatus];
    }, [presence]);

    const activity = useMemo(() => {
        return presence?.activities?.find((x: { type: number; }) => x.type === 0);
    }, [presence]);

    // @ts-ignore
    return (
        <section className="flex flex-1 mb-4">
            <div className="flex flex-col w-full">
                {presence ? (
                    <div
                        className="rounded-lg p-4 w-full max-w-xl bg-zinc-700 dark:bg-white/10 text-white dark:text-gray-300">
                        <div className="flex flex-col items-center sm:flex-row">
                            <img
                                className="w-28 h-28 rounded-full mb-4 sm:mb-0 sm:mr-4"
                                src={
                                    user!.avatar
                                        ? `https://cdn.discordapp.com/avatars/${user!.id}/${user!.avatar}.gif?size=128`
                                        : `https://cdn.discordapp.com/embed/avatars/${
                                            parseInt(user!.discriminator.slice(-1), 10) % 5
                                        }.png`
                                }
                                alt="User Avatar"
                            />
                            <div>
                                <h4 className="text-xl font-bold leading-6">
                                    {user!.username}
                                    <span className="font-normal text-gray-400 ml-1 text-lg">
                  #{user!.discriminator}
                </span>
                                </h4>
                                <div
                                    className="flex flex-row items-center justify-center text-gray-400 sm:justify-start">
                                    <div
                                        className={`w-4 h-4 rounded-full ${
                                            StatusColor[presence.discord_status as keyof typeof StatusColor]
                                        } mr-2`}
                                    />
                                    <span>{status}</span>
                                </div>
                            </div>
                        </div>
                        {presence.listening_to_spotify && (
                            <div className="mt-4">
                                <h5 className="ml-1 mb-1 text-sm font-bold opacity-70">Listening</h5>
                                <div
                                    className="flex items-center justify-center rounded-lg overflow-hidden p-4 bg-[rgba(0,0,0,.2)]">
                                    <div
                                        className="w-20 h-20 min-w-[5rem] flex items-center justify-center relative mr-4">
                                        <img
                                            className="rounded-xl"
                                            src={`${presence.spotify!.album_art_url}`}
                                            alt={`${presence.spotify!.song} art`}
                                        />
                                        <FaSpotify
                                            className="w-6 h-6 border-2 rounded-full bg-black border-black absolute bottom-[-8px] right-[-8px]"/>
                                    </div>
                                    <div className="flex flex-col">
                                        <a href={`https://open.spotify.com/track/` + presence.spotify!.track_id}
                                           className="mr-auto" target="_blank" rel="noreferrer">
                                            <h4 className="text-lg font-bold text-white hover:underline mr-auto">{presence.spotify!.song}</h4>
                                        </a>
                                        <span
                                            className="text-sm text-gray-300 opacity-50">by {presence.spotify!.artist}</span>
                                        <small
                                            className="text-xs text-gray-300 opacity-50">on {presence.spotify!.album}</small>
                                    </div>
                                    <section className="flex flex-1 items-center mb-6">
                                        <div className="mt-2">
                                            <div className="rounded-lg bg-gray-200/20 h-2">
                                                <div className="rounded-lg bg-white/75 h-2 transition-all"
                                                     style={{width: '50%'}}/>
                                            </div>
                                        </div>
                                    </section>
                                </div>
                            </div>
                        )}
                        {activity && (
                            <div className="mt-4">
                                <h5 className="ml-1 mb-1 text-sm font-bold opacity-70">Doing
                                    something</h5>
                                <div
                                    className="flex flex-row items-center rounded-lg overflow-hidden p-4 bg-[rgba(0,0,0,.2)]">
                                    <div
                                        className="w-20 h-20 min-w-[5rem] flex items-center justify-center bg-black rounded-xl relative mr-4">
                                        <img
                                            className="rounded-xl"
                                            src={
                                                activity.assets?.large_image
                                                    ? getAssetUrl(activity.application_id!, activity.assets.large_image)
                                                    : `https://dcdn.dstn.to/app-icons/${activity.application_id}`
                                            }
                                            alt="App Large Image"
                                        />
                                        {activity.assets?.small_image && (
                                            <img
                                                className="w-8 h-8 border-2 rounded-full bg-black border-black absolute bottom-[-8px] right-[-8px]"
                                                src={getAssetUrl(activity.application_id!, activity.assets.small_image!)}
                                                alt="App Small Image"
                                            />
                                        )}
                                    </div>
                                    <div className="flex flex-col">
                                        <h5 className="font-bold leading-4 mb-1">{activity.name}</h5>
                                        <span className="text-sm text-gray-300 opacity-50">{activity.state}</span>
                                        {activity.details && (
                                            <span className="text-sm text-gray-300 opacity-50">{activity.details}</span>
                                        )}
                                        {activity.timestamps && (
                                            <span className="text-sm text-gray-300 opacity-50">
                                                {getElapsedTime(activity.timestamps.start)}
                                            </span>
                                        )}
                                    </div>
                                </div>
                            </div>
                        )}
                    </div>
                ) : (
                    <section className="flex-1 items-center mb-4">
                        <div
                            className="rounded-lg flex items-center flex-row bg-white/10 p-4 overflow-x-hidden text-white items-center">
                            <AiOutlineLoading3Quarters className="animate-spin mr-2"/>
                            <span className="text-sm opacity-90 text-gray-100 dark:text-white">
                    Loading status <span className="text-gray-300 animate-pulse">...</span>
                    </span>
                        </div>
                    </section>
                )}
            </div>
        </section>
    );
}

export default Listening;
ebykdrms
752 gün önce

Şöyle bir yol izleyebilirsiniz:

function Listening() {
    
    const [elapsedTime, setElapsedTime] = useState(null);
    
    useEffect(()=>{
        setTimeout(()=>{
            if(activity?.timestamps?.start) {
                setElapsedTime(getElapsedTime(activity.timestamps.start));
            }
        },1000);
    },[elapsedTime];

return ettiğiniz bileşende geçen {getElapsedTime(activity.timestamps.start)} kısmında direkt elapsedTime state'ini yazarsınız.
Denemek lazım...

Ama aslında çok daha güzeli, eğer bu bölüm diğer bölümlerin değişmesine neden olmuyorsa bu bölümü kendi component'ine ayırmak daha uygun olur. Böylece her değişimde tüm bileşenin render edilmesi yerine sadece bu bileşen render edilmiş olur.

const ElapsedTime = ({start}) => {
     const [elapsedTime, setElapsedTime] = useState(null);
     
     useEffect(()=>{
        setTimeout(()=>{
            if(start) {
                setElapsedTime(getElapsedTime(start));
            }
        },1000);
    },[elapsedTime];
    
    return (
        <span className="text-sm text-gray-300 opacity-50">
            {elapsedTime}
        </span>
    )
}

Kodunuzdaki ilgili yere bu bileşeni yerleştirirseniz, bu bileşenin state değişimi üst bileşenin yeniden render edilmesini gerektirmeyecektir.

<div className="flex flex-col">
    <h5 className="font-bold leading-4 mb-1">{activity.name}</h5>
    <span className="text-sm text-gray-300 opacity-50">{activity.state}</span>
    {activity.details && (
        <span className="text-sm text-gray-300 opacity-50">{activity.details}</span>
    )}
    {activity.timestamps && (
        <span className="text-sm text-gray-300 opacity-50">
            <ElapsedTime start={activity.timestamps?.start} />
        </span>
    )}
</div>