Handwritten React-hooks

useCallback

useCallback is the Hook of the callback function used to create the cache. It takes a callback function and an array of dependencies and returns a cached version. When the dependent array changes, useCallback will return a new callback function.

Source code logic

// Import variables and functions related to state and state index
import {<!-- --> hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useCallback Hook
export function useCallback(callback, deps) {<!-- -->
  // if the last state exists
  if (hookStates[hookIndex]) {<!-- -->
    const [lastCallback, lastDeps] = hookStates[hookIndex];
    // Determine whether the dependent arrays are completely equal
    const same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {<!-- -->
      // If they are equal, return directly to the previous callback function
      setHookIndexAdd();
      return lastCallback;
    } else {<!-- -->
      // If not equal, update state and return new callback function
      setHookStates(setHookIndexAdd(), [callback, deps]);
      return callback;
    }
  } else {<!-- -->
    // If this is the first call, set the state and return the callback function
    setHookStates(setHookIndexAdd(), [callback, deps]);
    return callback;
  }
}

Example usage

const ExampleComponent = () => {<!-- -->
  const handleClick = useCallback(() => {<!-- -->
    console.log('Button clicked');
  }, []);

  return <button onClick={<!-- -->handleClick}>Click me</button>;
};

useMemo

useMemo is used to create a Hook for cached values. It takes a callback function and an array of dependencies and returns a cached value. When the dependent array changes, useMemo will recalculate and return a new value.

Source code logic

// Import variables and functions related to state and state index
import {<!-- --> hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useMemo Hook
export function useMemo(factory, deps) {<!-- -->
  // if the last state exists
  if (hookStates[hookIndex]) {<!-- -->
    let [lastMemo, lastDeps] = hookStates[hookIndex];
    // Determine whether the dependent arrays are completely equal
    let same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {<!-- -->
      // If equal, return the last cached value directly
      setHookIndexAdd();
      return lastMemo;
    } else {<!-- -->
      // If not equal, execute the factory function to create a new cache value
      let newMemo = factory();
      // update the state and return the new cached value
      setHookStates(setHookIndexAdd(), [newMemo, deps]);
      return newMemo;
    }
  } else {<!-- -->
    // If it is the first call, execute the factory function to create a new cache value
    let newMemo = factory();
    // set state and return new cached value
    setHookStates(setHookIndexAdd(), [newMemo, deps]);
    return newMemo;
  }
}

Example usage

const ExampleComponent = () => {<!-- -->
  const expensiveValue = useMemo(() => {<!-- -->
    // perform some expensive calculations
    return computeExpensiveValue();
  }, []);

  return <div>{<!-- -->expensiveValue}</div>;
};

useState

useState is a Hook for adding state in function components. It takes an initial state and returns an array of the current state and a function to update the state.

Source code logic

// Import variables and functions related to state and state index
import {<!-- --> hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useState implementation
export const useState = (initialState, render) => {<!-- -->
  // If the state does not exist, set the initial state
  hookStates[hookIndex] = hookStates[hookIndex] || initialState;
  const currentIndex = hookIndex;
  
  const setState = (newState) => {<!-- -->
    // update status
    if (typeof newState === 'function') {<!-- -->
      // If the new state is a function, call it, passing the current state as an argument
      setHookStates(currentIndex, newState(hookStates[currentIndex]));
    } else {<!-- -->
      // If the new state is not a function, set it directly to the value of the new state
      setHookStates(currentIndex, newState);
    }
    
    // Trigger the component to re-render
    render();
  };

  // Functions that return the current state and set the state
  return [hookStates[setHookIndexAdd()], setState];
}

Example usage

const ExampleComponent = () => {<!-- -->
  const [count, setCount] = useState(0);

  const increment = () => {<!-- -->
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {<!-- -->count}</p>
      <button onClick={<!-- -->increment}>Increment</button>
    </div>
  );
};

useEffect

useEffect is a Hook for performing side effects in function components. It takes a side effect function and an array of dependencies and executes the side effect function after each render.

Source code logic

// Import variables and functions related to state and state index
import {<!-- --> hookStates, hookIndex, setHookStates, setHookIndexAdd } from "./state";

// useEffect implementation
export const useEffect = (callback, deps) => {<!-- -->
  // if the last state exists
  if (hookStates[hookIndex]) {<!-- -->
    const [oldDestroy, lastDeps] = hookStates[hookIndex];
    // Determine whether the dependent arrays are completely equal
    const same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {<!-- -->
      // If equal, directly update the state index
      setHookIndexAdd();
    } else {<!-- -->
      // If not equal, execute the previous clear function, set the new state, and execute the callback function after a delay
      oldDestroy();
      setHookStates(setHookIndexAdd(), [callback, deps]);
      setTimeout(callback);
    }
  } else {<!-- -->
    // If it is called for the first time, execute the callback function to get the clearing function and set the state
    let destroy = callback();
    setHookStates(setHookIndexAdd(), [destroy, deps]);
  }
};

Example usage

const ExampleComponent = () => {<!-- -->
  useEffect(() => {<!-- -->
    console.log('Component mounted');
    return () => {<!-- -->
      console.log('Component unmounted');
    };
  }, []);

  return <div>Example Component</div>;
};

useRef

useRef is used to create variable reference Hook in function components. It returns an object containing a mutable reference that remains constant throughout the lifetime of the component.

Source code logic

// Import useState and useEffect
import {<!-- --> useState, useEffect } from 'react';

// useRef implementation
export function useRef(initialValue) {<!-- -->
  // Create a state using useState ref
  const [ref] = useState(() => ({<!-- -->
    current: initialValue,
  }));

  // Use useEffect to update the current value of ref when initialValue changes
  useEffect(() => {<!-- -->
    ref. current = initialValue;
  }, [initialValue]);

  // return the ref object
  return ref;
}

Example usage

const ExampleComponent = () => {<!-- -->
  const inputRef = useRef(null);

  const focusInput = () => {<!-- -->
    inputRef. current. focus();
  };

  return (
    <div>
      <input ref={<!-- -->inputRef} />
      <button onClick={<!-- -->focusInput}>Focus Input</button>
    </div>
  );
};

useContext

useContext is used to access context Hook in function components. It takes a context object and returns the current value of that context.

Source code logic

export function useContext(context) {<!-- -->
  return context._currentValue;
}

Example usage

const MyContext = React.createContext();

const ExampleComponent = () => {<!-- -->
  const value = useContext(MyContext);

  return <div>{<!-- -->value}</div>;
};

useReducer

useReducer is a Hook used to manage state in function components. It takes a state update function and an initial state, and returns the current state and a function to dispatch state updates.

Source code logic

// Import variables and functions related to state and state index
import {<!-- --> hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useReducer implementation
export function useReducer(reducer, initialState, render) {<!-- -->
  // If the state does not exist, set the initial state
  hookStates[hookIndex] = hookStates[hookIndex] || initialState;
  let currentIndex = hookIndex;

  // define the dispatch function
  function dispatch(action) {<!-- -->
    // update state according to reducer or action
    hookStates[currentIndex] = reducer
      ? reducer(hookStates[currentIndex], action)
      : action;
    // Trigger the component to re-render
    render();
  }

  // return current state and dispatch function
  return [hookStates[setHookIndexAdd()], dispatch];
}

Example usage

const initialState = {<!-- --> count: 0 };

function reducer(state, action) {<!-- -->
  switch (action.type) {<!-- -->
    case 'increment':
      return {<!-- --> count: state.count + 1 };
    case 'decrement':
      return {<!-- --> count: state.count - 1 };
    default:
      return state;
  }
}

const ExampleComponent = () => {<!-- -->
  const [state, dispatch] = useReducer(reducer, initialState);

  const increment = () => {<!-- -->
    dispatch({<!-- --> type: 'increment' });
  };

  const decrement = () => {<!-- -->
    dispatch({<!-- --> type: 'decrement' });
  };

  return (
    <div>
      <p>Count: {<!-- -->state.count}</p>
      <button onClick={<!-- -->increment}>Increment</button>
      <button onClick={<!-- -->decrement}>Decrement</button>
    </div>
  );
};