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>
);
};