Okay codes
Riku Rouvilahello@rikurouvila.fi +358504700715CVGitHub icon
Published on Nov 29th 2018

React Hook for showing custom "Add to homescreen" prompt

Demo:
Twitter

Simple React Hook for showing the user a custom "Add to homescreen" prompt.

const [prompt, promptToInstall] = useAddToHomescreenPrompt();

Listens for beforeinstallprompt event, which notifies you when the browser would have shown the default dialog, intercepts it and lets you take over and show the prompt when ever you please.

Browser support and requirements

Add to Home Screen

Browser support is still quite lacking. At the time of writing, only Chrome (Desktop + Android) is supported.

Implementation

import * as React from "react";

interface IBeforeInstallPromptEvent extends Event {
  readonly platforms: string[];
  readonly userChoice: Promise<{
    outcome: "accepted" | "dismissed";
    platform: string;
  }>;
  prompt(): Promise<void>;
}

export function useAddToHomescreenPrompt(): [
  IBeforeInstallPromptEvent | null,
  () => void
] {
  const [prompt, setState] = React.useState<IBeforeInstallPromptEvent | null>(
    null
  );

  const promptToInstall = () => {
    if (prompt) {
      return prompt.prompt();
    }
    return Promise.reject(
      new Error(
        'Tried installing before browser sent "beforeinstallprompt" event'
      )
    );
  };

  React.useEffect(() => {
    const ready = (e: IBeforeInstallPromptEvent) => {
      e.preventDefault();
      setState(e);
    };

    window.addEventListener("beforeinstallprompt", ready as any);

    return () => {
      window.removeEventListener("beforeinstallprompt", ready as any);
    };
  }, []);

  return [prompt, promptToInstall];
}

Example component

import * as React from "react";
import { useAddToHomescreenPrompt } from "./useAddToHomescreenPrompt";

export function ExampleComponent() {
  const [prompt, promptToInstall] = useAddToHomescreenPrompt();
  const [isVisible, setVisibleState] = React.useState(false);

  const hide = () => setVisibleState(false);

  React.useEffect(
    () => {
      if (prompt) {
        setVisibleState(true);
      }
    },
    [prompt]
  );

  if (!isVisible) {
    return <div />;
  }

  return (
    <div onClick={hide}>
      <button onClick={hide}>Close</button>
      Hello! Wanna add to homescreen?
      <button onClick={promptToInstall}>Add to homescreen</button>
    </div>
  );
}

I love feedback!

First of all: thank you so much for reading!
If you have something to ask, don't agree with something I say or just wanna have a chat, feel free to ping me on Twitter.

Freelance Software Developer in Tampere, FinlandRiku Rouvila
Software developer