text: // @flow
  import { useRef, useState, useEffect } from 'react';
  import areInputsEqual from './are-inputs-equal';
  
  type Cache<T> = {|
    inputs: ?(mixed[]),
    result: T,
  |};
  
  export function useMemoOne<T>(
    // getResult changes on every call,
    getResult: () => T,
    // the inputs array changes on every call
    inputs?: mixed[],
  ): T {
    // using useState to generate initial value as it is lazy
    const initial: Cache<T> = useState(() => ({
      inputs,
      result: getResult(),
    }))[0];
  
    const committed = useRef<Cache<T>>(initial);
  
    // persist any uncommitted changes after they have been committed
  
    const isInputMatch: boolean = Boolean(
      inputs &&
        committed.current.inputs &&
        areInputsEqual(inputs, committed.current.inputs),
    );
  
    // create a new cache if required
    const cache: Cache<T> = isInputMatch
      ? committed.current
      : {
          inputs,
          result: getResult(),
        };
  
    // commit the cache
    useEffect(() => {
      committed.current = cache;
    }, [cache]);
  
    return cache.result;
  }
  
  export function useCallbackOne<T: Function>(
    // getResult changes on every call,
    callback: T,
    // the inputs array changes on every call
    inputs?: mixed[],
  ): T {
    return useMemoOne(() => callback, inputs);
  }
  