React 这些Hooks可能是你不知道的

117 阅读2分钟

WechatIMG113.jpg

React HooksReact 16.8 版本引入的新特性,它们允许你在函数组件中使用 state 以及其他 React 特性,而无需编写 class 组件。Hooks 的引入,使得我们可以在不使用类的情况下构建 React 应用程序,同时提高了组件逻辑的复用性,并使代码更加清晰易懂。

  • useState Hook
  • useEffect Hook
  • useContext Hook
  • useReducer Hook
  • useRef Hook
  • useCallback Hook
  • useMemo Hook
  • useImperativeHandle Hook
  • useLayoutEffect Hook
  • useDebugValue Hook

1. useState Hook

在函数式组件中管理局部状态。

import React, { useState } from 'react';

const Example = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
};

2. useEffect Hook

处理副作用,例如数据获取、订阅或手动更改DOM

import React, { useState, useEffect } from 'react';

const Example = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(json => setData(json));
  }, []); // 空依赖数组确保仅在组件挂载时运行

  return <ul>{data.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
};

3. useContext Hook

跨层级组件传递数据,避免手动逐层传递 props

import React, { createContext, useContext } from 'react';

const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>I am styled by theme context!</button>;
}

4. useReducer Hook

适用于复杂状态逻辑,通过分发action来更新状态。

import React, { useReducer } from 'react';

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:
      throw new Error();
  }
}

const Example = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </div>
  );
};

5. useRef Hook

创建对DOM元素或可变值的引用。

import React, { useRef } from 'react';

const Example = () => {
  const inputRef = useRef(null);

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

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
};

6. useCallback Hook

缓存函数实例,避免不必要的重新渲染。

import React, { useState, useCallback } from 'react';

const Example = () => {
  const [count, setCount] = useState(0);

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

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

7. useMemo Hook

缓存计算结果,避免重复计算。

import React, { useState, useMemo } from 'react';

const Example = () => {
  const [value, setValue] = useState(0);

  const doubledValue = useMemo(() => value * 2, [value]);

  return (
    <div>
      <p>Doubled Value: {doubledValue}</p>
      <button onClick={() => setValue(value + 1)}>Increment</button>
    </div>
  );
};

8. useImperativeHandle Hook

使父组件可以获取子组件实例的句柄,调用子组件的方法。

import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const Input = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));

  return <input ref={inputRef} {...props} />;
});

const App = () => {
  const inputRef = useRef();

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

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

9. useLayoutEffect Hook

在DOM更新后立即执行一些同步操作,例如获取DOM元素位置等。

import React, { useLayoutEffect, useState } from 'react';

function App() {
  const [value, setValue] = useState(0);

  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);

  console.log('render', value);

  return (
    <div onClick={() => setValue(0)}>
      Value: {value}
    </div>
  );
}

10. useDebugValue Hook

React 开发者工具中显示自定义 Hook 的标签,方便调试。

import React, { useDebugValue, useState } from 'react';
function useCustomHook(initialValue) {
  const [value, setValue] = useState(initialValue);
  useDebugValue(`Current value: ${value}`);
  return [value, setValue];
}

function App() {
  const [value, setValue] = useCustomHook(0);
  return (
    <div>
      <p>Value: {value}</p>
      <button onClick={() => setValue(value + 1)}>Increment</button>
    </div>
  );
}