import { useState, useEffect, useLayoutEffect, useRef } from 'react';

/**
 * https://github.com/the-road-to-learn-react/use-state-with-callback
 * @param {*} initialValue 
 * @param {*} callback 
 * @returns state, setState
 */
const useStateWithCallback = (initialValue, callback) => {
  const [state, setState] = useState(initialValue);

  useEffect(() => callback(state), [state, callback]);

  return [state, setState];
};

/**
 * https://github.com/the-road-to-learn-react/use-state-with-callback
 * @param {*} initialValue 
 * @param {*} callback 
 * @returns state, setState
 */
const useStateWithCallbackInstant = (initialValue, callback) => {
  const [state, setState] = useState(initialValue);

  useLayoutEffect(() => callback(state), [state, callback]);

  return [state, setState];
};

/**
 * https://github.com/the-road-to-learn-react/use-state-with-callback
 * @param {*} initialValue 
 * @returns state, setStateWithCallback
 */
const useStateWithCallbackLazy = initialValue => {
  const callbackRef = useRef(null);

  const [value, setValue] = useState(initialValue);
  useEffect(() => {
    if (callbackRef.current) {
      callbackRef.current(value);

      callbackRef.current = null;
    }
  }, [value]);

  const setValueWithCallback = (newValue, callback) => {
    callbackRef.current = callback;

    return setValue(newValue);
  };

  return [value, setValueWithCallback];
};

export { useStateWithCallbackInstant, useStateWithCallbackLazy };

export default useStateWithCallback;