相关文章
环境
hooks源码简化实现
useState
用于在函数组件中添加状态管理。useState 返回一个状态值以及更新该状态值的函数,允许函数组件在不使用类组件的情况下管理组件的状态。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import React, { useState } from 'react';
function Counter() { const [count, setCount] = useState(0);
const increment = () => { setCount(count + 1); };
const decrement = () => { setCount(count - 1); };
return ( <div> <h1>Counter</h1> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); }
export default Counter;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function useState(initialState) { // 获取当前组件实例 const component = getCurrentComponent();
// 判断是否已经有状态存在,如果不存在则初始化状态 if (!component.states[component.stateIndex]) { // 定义一个名为 state 的局部变量,并赋值为 initialState let state = initialState;
// 定义一个名为 setState 的更新状态的函数 function setState(newState) { // 将组件的状态数组中对应位置的值更新为新的状态值 component.states[component.stateIndex] = newState; // 触发组件的重新渲染 // 这里假设有一个名为 scheduleUpdate 的函数用于触发重新渲染 scheduleUpdate(); }
// 将状态值和更新函数返回给调用方 return [state, setState]; } else { // 如果状态已经存在,则直接返回当前状态值和对应的更新函数 return [ component.states[component.stateIndex], component.setStateCallbacks[component.stateIndex] ]; } }
|
useEffect
用于在函数组件中执行副作用操作,比如数据获取、订阅、DOM 操作等。useEffect 接收一个回调函数和一个依赖数组,当依赖数组中的值发生变化时,会触发回调函数的执行。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React, { useState, useEffect } from 'react';
function Example() { const [count, setCount] = useState(0);
useEffect(() => { console.log(`Count: ${count}`); });
return ( <div> <p>You clicked {count} times</p> {/* 点击按钮时,调用 setCount 更新 count 的值 */} <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
export default Example;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| function useEffect(callback, dependencies) { const component = getCurrentComponent();
const lastEffect = component.effects[component.effectIndex];
const dependenciesChanged = !lastEffect || !arraysEqual(lastEffect.dependencies, dependencies);
if (dependenciesChanged) { const effect = { callback, dependencies };
component.effects.push(effect); }
component.effectIndex++; }
function getCurrentComponent() { return getCurrentComponent(); }
function arraysEqual(a, b) { return arraysEqual(a, b); }
|
useContext
用于在函数组件中获取上下文(Context)的值。useContext 接收一个上下文对象作为参数,并返回上下文的当前值。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() { const theme = useContext(ThemeContext);
return ( <div className={theme}> <button onClick={toggleTheme}>Toggle Theme</button> </div> ); }
function AppWrapper() { return ( <ThemeContext.Provider value="dark"> <App /> </ThemeContext.Provider> ); }
export default AppWrapper;
|
简易源码
1 2 3 4 5 6 7
| function useContext(context) { const component = getCurrentComponent(); const value = component.context[context._contextID]; return value; }
|
useReducer
用于在函数组件中管理复杂的状态逻辑。useReducer 类似于 Redux 中的 reducer,接收一个 reducer 函数和初始状态作为参数,并返回一个状态值和 dispatch 函数,通过 dispatch 函数可以触发状态的更新。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import React, { useReducer } from 'react';
function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } }
function Counter() { const [state, dispatch] = useReducer(reducer, { count: 0 });
return ( <div> <p>Count: {state.count}</p> {/* 点击按钮时,触发 dispatch 函数执行对应的操作 */} <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); }
export default Counter;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function useReducer(reducer, initialState) { // 获取当前组件实例 const component = getCurrentComponent();
// 初始化状态值为初始状态 let state = initialState;
// 定义 dispatch 函数,用于触发状态的更新 function dispatch(action) { // 调用 reducer 函数获取新的状态值 state = reducer(state, action); // 触发组件的重新渲染 // 这里假设有一个名为 scheduleUpdate 的函数用于触发重新渲染 scheduleUpdate(); }
// 返回状态值和 dispatch 函数 return [state, dispatch]; }
|
useCallback
用于返回一个记忆化的回调函数,避免在每次渲染时创建新的回调函数。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import React, { useState, useCallback } from 'react';
function App() { const [count, setCount] = useState(0);
const handleClick = useCallback(() => { setCount(count + 1); }, [count]);
return ( <div> <p>Count: {count}</p> {/* 每次点击按钮都会调用缓存的回调函数 */} <button onClick={handleClick}>Increment</button> </div> ); }
export default App;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function useCallback(callback, dependencies) { const component = getCurrentComponent();
const dependenciesChanged = !component.lastDependencies || !arraysEqual(component.lastDependencies, dependencies);
if (dependenciesChanged) { component.lastCallback = callback; component.lastDependencies = dependencies; }
return component.lastCallback; }
|
useMemo
用于返回一个记忆化的值,仅在依赖项发生变化时重新计算。可以用于优化性能,避免不必要的计算。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import React, { useState, useMemo } from 'react';
function App() { const [number, setNumber] = useState(0);
const squaredNumber = useMemo(() => { console.log('Calculating squared number...'); return number * number; }, [number]);
return ( <div> <input type="number" value={number} onChange={(e) => setNumber(parseInt(e.target.value))} /> <p>Squared number: {squaredNumber}</p> </div> ); }
export default App;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function useMemo(factory, dependencies) { const component = getCurrentComponent();
const dependenciesChanged = !component.lastDependencies || !arraysEqual(component.lastDependencies, dependencies);
if (dependenciesChanged) { component.memoizedValue = factory(); component.lastDependencies = dependencies; }
return component.memoizedValue; }
|
useRef
用于在函数组件中创建可变的引用,可以用来存储组件的引用、DOM 元素的引用等。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React, { useRef } from 'react';
function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { inputEl.current.focus(); };
return ( <div> {/* 将 ref 对象赋值给组件的 DOM 节点 */} <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </div> ); }
|
简易源码
1 2 3 4 5
| function useRef(initialValue) { // 创建一个 ref 对象,包含一个名为 .current 的属性 const ref = { current: initialValue }; return ref; }
|
useImperativeHandle
用于在函数式组件中自定义向外暴露的实例值或方法。它允许你在函数式组件内部操作 ref 对象,并选择性地向外暴露指定的值或方法。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import React, { useRef, useImperativeHandle } from 'react';
const MyComponent = React.forwardRef((props, ref) => { const inputRef = useRef(null);
useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }, reset: () => { inputRef.current.value = ''; } }));
return ( <div> <input ref={inputRef} type="text" /> </div> ); });
const ParentComponent = () => { const childRef = useRef();
const handleFocus = () => { childRef.current.focus(); };
const handleReset = () => { childRef.current.reset(); };
return ( <div> <MyComponent ref={childRef} /> <button onClick={handleFocus}>Focus Input</button> <button onClick={handleReset}>Reset Input</button> </div> ); };
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import { useEffect, useRef } from 'react';
function useImperativeHandle(ref, createHandle) { const handleRef = useRef(null);
useEffect(() => { if (typeof createHandle === 'function') { const newHandle = createHandle(); for (const key in newHandle) { handleRef.current[key] = newHandle[key]; } } }, [createHandle]);
useEffect(() => { if (typeof ref === 'function') { ref(handleRef.current); } else if (ref !== null && typeof ref === 'object') { ref.current = handleRef.current; } }, [ref]);
return handleRef; }
export default useImperativeHandle;
|
useDebugValue
useDebugValue 是 React 提供的一个自定义 Hook,用于在开发者工具中显示自定义的调试信息。它允许开发者在开发过程中更方便地调试自定义 Hook 或其他自定义逻辑。
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import React, { useState, useEffect, useDebugValue } from 'react';
function useCurrentTime() { const [currentTime, setCurrentTime] = useState(new Date());
useEffect(() => { const interval = setInterval(() => { setCurrentTime(new Date()); }, 1000);
return () => clearInterval(interval); }, []);
useDebugValue(currentTime, date => date.toTimeString());
return currentTime; }
function App() { const currentTime = useCurrentTime();
return ( <div> <p>Current Time: {currentTime.toLocaleTimeString()}</p> </div> ); }
export default App;
|
简易源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { useEffect } from 'react';
function useDebugValue(value, formatter) { useEffect(() => { if (typeof formatter === 'function') { console.log(formatter(value)); } else { console.log(value); } }, [value, formatter]); }
export default useDebugValue
|