Skip to content

常用 Hooks 详解

useState - 状态管理

javascript
const [count, setCount] = useState(0);

// 函数式更新
setCount((prevCount) => prevCount + 1);

useReducer - 复杂状态管理

复杂状态管理,类似 Redux:

javascript
const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "ADD":
      return { count: state.count + 1 };
    case "MINUS":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: "ADD" });

useEffect - 副作用处理

处理副作用,替代类组件的生命周期:

javascript
useEffect(() => {
  // 相当于 componentDidMount
  const timer = setInterval(() => {
    setCount((count) => count + 1);
  }, 1000);

  // 返回清理函数,相当于 componentWillUnmount
  return () => {
    clearInterval(timer);
  };
}, []); // 空依赖数组 = 只执行一次

// 带依赖的 effect
useEffect(() => {
  // 当 count 变化时执行
  console.log("Count changed:", count);
}, [count]);

useContext - 跨组件共享数据

javascript
const MyContext = createContext("defaultValue");

// 提供数据
<MyContext.Provider value="hello">
  <Child />
</MyContext.Provider>;

// 消费数据
function Child() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}

useMemo - 缓存计算结果

javascript
const displayData = useMemo(() => ({ count }), [count]);

useCallback - 缓存回调函数

javascript
const incrementCount = useCallback(() => {
  setCount((count) => count + 1);
}, [count]);

useRef - 引用 DOM

在函数组件中创建 ref:

javascript
const inputRef = useRef(null); // {current: null}

function focusInput() {
  inputRef.current.focus();
}

<input ref={inputRef} />;

useImperativeHandle - 自定义 ref 暴露

自定义 ref 暴露给父组件的实例值:

javascript
function FancyInput(props, ref) {
  const inputRef = useRef();

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current.focus();
    },
  }));

  return <input ref={inputRef} />;
}

const ForwardFancyInput = forwardRef(FancyInput);

useLayoutEffect - 同步副作用

同步执行副作用,在 DOM 变更后同步调用(阻塞浏览器绘制):

javascript
useLayoutEffect(() => {
  // 在浏览器绘制之前执行
  ref.current.style.transform = `translate(500px)`;
}, []);

Ref 引用

createRef(类组件)

用于访问 DOM 元素或类组件实例:

javascript
class RefComponent extends React.Component {
  inputRef = React.createRef(); // {current: null}

  handleButtonClick = () => {
    this.inputRef.current.focus(); // 访问真实 DOM
  };

  render() {
    return (
      <div>
        <input ref={this.inputRef} type="text" />
        <button onClick={this.handleButtonClick}>获得焦点</button>
      </div>
    );
  }
}

访问类组件实例

javascript
class ParentComponent extends React.Component {
  childRef = React.createRef();

  handleClick = () => {
    this.childRef.current.alertMessage(); // 调用子组件方法
  };

  render() {
    return (
      <div>
        <ChildComponent ref={this.childRef} />
      </div>
    );
  }
}

forwardRef(转发 ref)

函数组件默认不能接收 ref,需要使用 forwardRef

javascript
function ChildComponent(props, forwardRef) {
  return <input ref={forwardRef} />;
}

const ForwardChildComponent = React.forwardRef(ChildComponent);