1.0.0 • Published 1 year ago

@mzaleski/use-send-code v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

useSendCode

A React (NextJS-oriented) hook that facilitates operations such as sending one-time codes.

Table of Contents


Features

  • Handle spam-sensitive operations such as one-time codes
  • Session tracking through server-only cookie
  • Session recovery on reload
  • Component (button) props that handle every aspect of the user-facing CTA (label, disabled, loading, etc)

Motivation

Low-cost solution to spam-sensitive operations. This solution omits the use of a cache which might not always be available in early-stage applications.

Caveat

This solution was designed around the ability to retrieve server-only cookies with relative ease, e.g. NextJS' getServerSideProps. A vanilla React application would not be suitable for this solution.

Installation

Install through your package manager of choice (npm, yarn, etc)

npm -i @mzaleski/use-send-code
yarn add @mzaleski/use-send-code

Usage

Example usage with NextJS' getServerSideProps:

import { useSendCode } from '@mzaleski/use-send-code';
import { Button } from 'src/components';

async function worker(iamIdentifier: string): Promise<void> { ... }

function AccountRecoveryPage({ cookiePayload }) {
  const { sendCode, status, buttonProps } = useSendCode(worker, {
    iamIdentifier: 'some-id',
    lastCodeIdentifier: cookiePayload?.iamIdentifier,
    lastCodeSendAt: cookiePayload?.sentAt,
    callOnMount: true,
    cooldownPeriod: 2 * 60,
    buttonPropsActiveLabel: 'Recover my account',
    buttonPropsLoadingPropName: 'isLoading',
    debugStatements: process.env.NODE_ENV === 'development',
    sessionClearHandler: async () => { ... },
    sessionPersistHandler: async (iamIdentifier) => { ... },
  });

  const sendRecoveryCode = async () => {
    const err = await sendCode();
    if (err) {
      // handle error
    }
  };

  return (
    <Button {...buttonProps} onClick={sendRecoveryCode} />
  );
}

export async function getServerSideProps(context) {
  /** retrieve server-only cookie and deserialise it */
  const cookiePayload = {...};

  return {
    props: {
      cookiePayload,
    },
  };
}

Configuration

The hook's configuration is done through the opts object which has the following properties:

NameTypeDescriptionDefault
iamIdentifierStringThe current user's unique identifierrequired
sessionClearHandlerFunctionA function responsible for clearing the server-only cookierequired
sessionPersistHandlerFunction- A function responsible for creating the server-only cookie; it is given the iamIdentifier as parameter - The signature encourages the return of a server timestamprequired
lastCodeIdentifier?Stringretrieved from server-only cookie the last code's iamIdentifierundefined
lastCodeSendAt?String, Numberretrieved from server-only cookie when the last code was sent; it will be parsed by the Javascript Date class. If the input is unparsable, the hook will throw InvalidLastCodeSentAtErrorundefined
callOnMount?BooleanWhether to call the worker on component mountfalse
cooldownPeriod?NumberThe cooldown period in seconds300 (5 minutes)
buttonPropsActiveLabel?StringThe button's label when a new code is available"Send me a new code"
buttonPropsLoadingPropName?StringCustom component support specify the loading boolean property name on a custom button component"loading"
debugStatements?BooleanWhether to log debug statements (requires development mode)false

Properties

The hook returns an object with the following properties:

NameTypeDescription
sendCodeFunctionThe function responsible for calling the worker and updating the internal state
resetFunctionWill reset the hook to a "READY" state; this same function is called once the cooldown has expired
statusStringThe current status of the hook; it can be one of the following: "READY", "COOLDOWN", "SENDING", "RESTORING"
buttonPropsObjectThe props that should be passed to the button component; affected by buttonPropsActiveLabel, buttonPropsLoadingPropName

Understanding the hook's behaviour

When a user clicks on the CTA

The hook will...

  1. Call your worker and perform the operation
  2. Call sessionPersistHandler with the given iamIdentifier to create a server-only cookie
  3. Update its internal state as well the button's props in order to reflect the change

When the cooldown is active, but the user refreshes the page

The hook will restore the previous state by looking at lastCodeIdentifier and lastCodeSendAt from the server-only cookie.

When the cooldown period is over

The hook will...

  1. Call sessionClearHandler to clear the server-only cookie
  2. Update its internal state as well the button's props in order to reflect the change

TypeScript Support

You will find a collection of typings bundled with the package.

License

MIT License (c) 2022 Maximilien Zaleski