DEV Community

Cover image for Creating a TimeoutMessage Component for Temporary User Messages in React
Radzion Chachura
Radzion Chachura

Posted on • Edited on • Originally published at radzion.com

Creating a TimeoutMessage Component for Temporary User Messages in React

Watch on YouTube | 🐙 GitHub | 🎮 Demo

There is a useful UX pattern of displaying a temporary message in response to a user's action. Recently, I had to add such a timeout message to my project and I thought it might be beneficial to package it into an abstract component and share it with you.

How To Use the TimeoutMessage Component

Here's how you can use it to display a temporary message after a user updates their profile.

Update Profile Message

If one of the values in the deps array has changed, the component will call the render function and display the message for five seconds.

<TimeoutMessage
  deps={[isAnonymous, name, country]}
  timeout={5000}
  render={() => <UpdateProfileMessage />}
/>
Enter fullscreen mode Exit fullscreen mode

TimeoutMessage Component

The TimeoutMessage component is a simple wrapper around the useTimeoutState and useEffectOnDependencyChange hooks. Instead of using those hooks directly, we achieve a more declarative and compact code using the TimeoutMessage component.

import { DependencyList, ReactNode } from "react"
import { useEffectOnDependencyChange } from "../hooks/useEffectOnDependencyChange"
import { useTimeoutState } from "../hooks/useTimeoutState"

interface TimeoutMessageProps {
  render: () => ReactNode
  timeout: number
  deps: DependencyList
}

export const TimeoutMessage = ({
  render,
  timeout,
  deps,
}: TimeoutMessageProps) => {
  const [shouldShowMessage, setShouldShowMessage] = useTimeoutState(
    false,
    timeout
  )

  useEffectOnDependencyChange(() => {
    setShouldShowMessage(true)
  }, deps)

  return shouldShowMessage ? <>{render()}</> : null
}
Enter fullscreen mode Exit fullscreen mode

useTimeoutState Hook

The useTimeoutState hook is similar to the useState hook, but it resets the state to the default value after a given timeout.

import { useEffect, useState } from "react"

export const useTimeoutState = <T,>(
  defaultValue: T,
  timeoutDuration: number
) => {
  const [state, setState] = useState(defaultValue)

  useEffect(() => {
    if (state !== defaultValue) {
      const timeout = setTimeout(() => {
        setState(defaultValue)
      }, timeoutDuration)

      return () => clearTimeout(timeout)
    }
  }, [state, defaultValue, setState, timeoutDuration])

  return [state, setState] as const
}
Enter fullscreen mode Exit fullscreen mode

In our TimeoutMessage component, we use useTimeoutState to monitor the message visibility. We set shouldShowMessage to true when the deps change, and the useTimeoutState hook will reset it back to false after the specified timeout.

useEffectOnDependencyChange Hook

The useEffectOnDependencyChange hook is the same as the useEffect hook. However, it only calls the effect function when one of the values in the deps array has changed, and will not call it on the initial render.

import { DependencyList, useEffect, useRef } from "react"

export const useEffectOnDependencyChange = (
  effect: () => void,
  deps: DependencyList
) => {
  const prevDeps = useRef(deps)
  useEffect(() => {
    const hasDepsChanged = !prevDeps.current.every((dep, i) => dep === deps[i])
    if (hasDepsChanged) {
      effect()
      prevDeps.current = deps
    }
  }, deps)
}
Enter fullscreen mode Exit fullscreen mode

Billboard image

Use Playwright to test. Use Playwright to monitor.

Join Vercel, CrowdStrike, and thousands of other teams that run end-to-end monitors on Checkly's programmable monitoring platform.

Get started now!

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay