Next.js Discord

Discord Forum

How to refresh data periodically without reloading the page?

Answered
Blue swimming crab posted this in #help-forum
Open in Discord
Avatar
Blue swimming crabOP
Hi everyone, this might sound like a basic question but I'm not sure how to solve it best:
I'm using Next.js 13 with the app dir and am fetching data with Prisma in a few server components.
I'd like to refresh those server components every few seconds so the user doesn't have to refresh the page to get updated data.
What's the best way to do this?
Answered by Blue swimming crab
I solved it now with server actions: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions

The component is a client component now:
'use client'

import { FC } from 'react'

import { DataTile } from '../data-tile'
import { useInterval } from '../use-interval'
import { getActiveRaids } from './get-active-raids'

export const ActiveRaids: FC = () => {
  const activeRaidCount = useInterval(getActiveRaids, 60_000)

  return <DataTile iconSrc='/raid.png' metric={activeRaidCount} metricUnit='Raids' secondLine='ready for battle' />
}

useInterval() is a small hook that calls the given method periodically and returns the result.

getActiveRaids is a server action now:
'use server'

import { prisma } from '@/utils/prisma'

export const getActiveRaids = () =>
  prisma.gym.count({
    where: { raid_end_timestamp: { gte: Math.floor(Date.now() / 1000) } },
  })


It works, could probably use some optimization though 😄 An advantage over router.refresh() might be that I don't have to refresh all server components at once as I have different intervals for each "data tile".
View full answer

7 Replies

Avatar
American Shorthair
@Blue swimming crab try to use hooks like useState and useEffect in order to check variable state and refresh content with useEffect providing const as dependency
Avatar
Blue swimming crabOP
@American Shorthair So in a client component then? How would I refresh a server component from there?
Avatar
American Shorthair
@Blue swimming crab could you show your components for better understanding?
Avatar
Blue swimming crabOP
One component here for example:
import { cache, FC } from 'react'

import { prisma } from '@/utils/prisma'

import { DataTile } from './data-tile'

export const ActiveRaids: FC = async () => {
  const activeRaidCount = await cache(
    async () =>
      await prisma.gym.count({
        where: { raid_end_timestamp: { gte: Math.floor(Date.now() / 1000) } },
      }),
  )()

  return <DataTile iconSrc='/raid.png' metric={activeRaidCount} metricUnit='Raids' secondLine='ready for battle' />
}


I'm then using it in a page.tsx page file.
The DataTile component just formats the data in a pretty way, nothing special in there.
Avatar
Barbary Lion
Interested in this as well
Avatar
andrewscofield
I haven't tried this yet myself, but if I'm reading the docs correctly, you can do this using router.refresh() from the client side, see docs here: https://nextjs.org/docs/app/api-reference/functions/use-router#userouter

It should refresh server components and call your prisma function again. I'm not sure how this works with the cache function you're using though
Avatar
Blue swimming crabOP
I solved it now with server actions: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions

The component is a client component now:
'use client'

import { FC } from 'react'

import { DataTile } from '../data-tile'
import { useInterval } from '../use-interval'
import { getActiveRaids } from './get-active-raids'

export const ActiveRaids: FC = () => {
  const activeRaidCount = useInterval(getActiveRaids, 60_000)

  return <DataTile iconSrc='/raid.png' metric={activeRaidCount} metricUnit='Raids' secondLine='ready for battle' />
}

useInterval() is a small hook that calls the given method periodically and returns the result.

getActiveRaids is a server action now:
'use server'

import { prisma } from '@/utils/prisma'

export const getActiveRaids = () =>
  prisma.gym.count({
    where: { raid_end_timestamp: { gte: Math.floor(Date.now() / 1000) } },
  })


It works, could probably use some optimization though 😄 An advantage over router.refresh() might be that I don't have to refresh all server components at once as I have different intervals for each "data tile".
Answer