手写React-hooks

useCallback

useCallback是用于创建缓存的回调函数的Hook。它接受一个回调函数和一个依赖数组,并返回一个被缓存的版本。当依赖数组发生变化时,useCallback会返回一个新的回调函数。

源码逻辑

// 导入状态和状态索引相关的变量和函数
import { hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useCallback Hook
export function useCallback(callback, deps) {
  // 如果存在上一次的状态
  if (hookStates[hookIndex]) {
    const [lastCallback, lastDeps] = hookStates[hookIndex];
    // 判断依赖数组是否完全相等
    const same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {
      // 如果相等,则直接返回上一次的回调函数
      setHookIndexAdd();
      return lastCallback;
    } else {
      // 如果不相等,则更新状态并返回新的回调函数
      setHookStates(setHookIndexAdd(), [callback, deps]);
      return callback;
    }
  } else {
    // 如果是第一次调用,则设置状态并返回回调函数
    setHookStates(setHookIndexAdd(), [callback, deps]);
    return callback;
  }
}

示例用法

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

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

useMemo

useMemo用于创建缓存的值的Hook。它接受一个回调函数和一个依赖数组,并返回一个被缓存的值。当依赖数组发生变化时,useMemo会重新计算并返回新的值。

源码逻辑

// 导入状态和状态索引相关的变量和函数
import { hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useMemo Hook
export function useMemo(factory, deps) {
  // 如果存在上一次的状态
  if (hookStates[hookIndex]) {
    let [lastMemo, lastDeps] = hookStates[hookIndex];
    // 判断依赖数组是否完全相等
    let same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {
      // 如果相等,则直接返回上一次的缓存值
      setHookIndexAdd();
      return lastMemo;
    } else {
      // 如果不相等,则执行工厂函数创建新的缓存值
      let newMemo = factory();
      // 更新状态并返回新的缓存值
      setHookStates(setHookIndexAdd(), [newMemo, deps]);
      return newMemo;
    }
  } else {
    // 如果是第一次调用,则执行工厂函数创建新的缓存值
    let newMemo = factory();
    // 设置状态并返回新的缓存值
    setHookStates(setHookIndexAdd(), [newMemo, deps]);
    return newMemo;
  }
}

示例用法

const ExampleComponent = () => {
  const expensiveValue = useMemo(() => {
    // 执行一些昂贵的计算
    return computeExpensiveValue();
  }, []);

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

useState

useState是用于在函数组件中添加状态的Hook。它接受一个初始状态,并返回一个由当前状态和更新状态的函数组成的数组。

源码逻辑

// 导入状态和状态索引相关的变量和函数
import { hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useState实现
export const useState = (initialState, render) => {
  // 如果状态不存在,则设置初始状态
  hookStates[hookIndex] = hookStates[hookIndex] || initialState;
  const currentIndex = hookIndex;
  
  const setState = (newState) => {
    // 更新状态
    if (typeof newState === 'function') {
      // 如果新状态是一个函数,则调用它,并将当前状态作为参数传递
      setHookStates(currentIndex, newState(hookStates[currentIndex]));
    } else {
      // 如果新状态不是函数,则直接设置为新状态的值
      setHookStates(currentIndex, newState);
    }
    
    // 触发组件重新渲染
    render();
  };

  // 返回当前状态和设置状态的函数
  return [hookStates[setHookIndexAdd()], setState];
}

示例用法

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用于在函数组件中执行副作用操作的Hook。它接受一个副作用函数和一个依赖数组,并在每次渲染后执行该副作用函数。

源码逻辑

// 导入状态和状态索引相关的变量和函数
import { hookStates, hookIndex, setHookStates, setHookIndexAdd } from "./state";

// useEffect实现
export const useEffect = (callback, deps) => {
  // 如果存在上一次的状态
  if (hookStates[hookIndex]) {
    const [oldDestroy, lastDeps] = hookStates[hookIndex];
    // 判断依赖数组是否完全相等
    const same = deps.every((item, index) => item === lastDeps[index]);
    if (same) {
      // 如果相等,则直接更新状态索引
      setHookIndexAdd();
    } else {
      // 如果不相等,则执行上一次的清除函数,设置新的状态,并在延迟后执行回调函数
      oldDestroy();
      setHookStates(setHookIndexAdd(), [callback, deps]);
      setTimeout(callback);
    }
  } else {
    // 如果是第一次调用,则执行回调函数获取清除函数,并设置状态
    let destroy = callback();
    setHookStates(setHookIndexAdd(), [destroy, deps]);
  }
};

示例用法

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

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

useRef

useRef用于在函数组件中创建可变的引用的Hook。它返回一个包含可变引用的对象,该引用在组件的整个生命周期内保持不变。

源码逻辑

// 导入 useState 和 useEffect
import { useState, useEffect } from 'react';

// useRef 实现
export function useRef(initialValue) {
  // 使用 useState 创建一个状态 ref
  const [ref] = useState(() => ({
    current: initialValue,
  }));

  // 使用 useEffect 在 initialValue 变化时更新 ref 的 current 值
  useEffect(() => {
    ref.current = initialValue;
  }, [initialValue]);

  // 返回 ref 对象
  return ref;
}

示例用法

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用于在函数组件中访问上下文的Hook。它接受一个上下文对象,并返回该上下文的当前值。

源码逻辑

export function useContext(context) {
  return context._currentValue;
}

示例用法

const MyContext = React.createContext();

const ExampleComponent = () => {
  const value = useContext(MyContext);

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

useReducer

useReducer是用于在函数组件中管理状态的Hook。它接受一个状态更新函数和一个初始状态,并返回当前状态和一个派发状态更新的函数。

源码逻辑

// 导入状态和状态索引相关的变量和函数
import { hookStates, hookIndex, setHookStates, setHookIndexAdd } from './state';

// useReducer 实现
export function useReducer(reducer, initialState, render) {
  // 如果状态不存在,则设置初始状态
  hookStates[hookIndex] = hookStates[hookIndex] || initialState;
  let currentIndex = hookIndex;

  // 定义 dispatch 函数
  function dispatch(action) {
    // 根据 reducer 或者 action 更新状态
    hookStates[currentIndex] = reducer
      ? reducer(hookStates[currentIndex], action)
      : action;
    // 触发组件重新渲染
    render();
  }

  // 返回当前状态和 dispatch 函数
  return [hookStates[setHookIndexAdd()], dispatch];
}

示例用法

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>
  );
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值