react hooks 是什么,react hooks 常见用法

阅读 62

08-08 09:00

React Hooks 是 React 16.8 引入的特性,它让函数组件能够拥有类组件的状态管理和生命周期等能力,无需编写类组件就能实现更复杂的逻辑。Hooks 解决了类组件中代码复用难、逻辑分散等问题,让代码更简洁、易维护。

下面介绍几个常见的 React Hooks 及其用法:

1. useState:管理组件状态

useState 用于在函数组件中添加状态,它返回一个状态变量和更新该状态的函数。

import { useState } from 'react';

function Counter() {
  // 声明一个count状态,初始值为0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>你点击了 {count} 次</p>
      <button onClick={() => setCount(count + 1)}>
        点击增加
      </button>
      <button onClick={() => setCount(0)}>
        重置
      </button>
    </div>
  );
}

2. useEffect:处理副作用

useEffect 可以让函数组件执行类似类组件中生命周期的操作,如数据获取、订阅、DOM 操作等。它相当于 componentDidMountcomponentDidUpdatecomponentWillUnmount 的组合。

import { useState, useEffect } from 'react';

function UserInfo({ userId }) {
  const [user, setUser] = useState(null);

  // 组件挂载和userId变化时执行
  useEffect(() => {
    // 获取用户数据
    const fetchUser = async () => {
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
    };

    fetchUser();

    // 清理函数,在组件卸载或userId变化前执行
    return () => {
      // 比如取消请求等操作
    };
  }, [userId]); // 依赖项数组,只有userId变化时才会重新执行

  if (!user) return <div>加载中...</div>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>年龄:{user.age}</p>
    </div>
  );
}

3. useContext:共享状态

useContext 用于在组件树中共享状态,避免通过 props 层层传递。

首先创建上下文:

import { createContext } from 'react';

const ThemeContext = createContext('light');

然后在组件中使用:

import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function ThemedButton() {
  // 获取上下文的值
  const theme = useContext(ThemeContext);

  return (
    <button style={{ 
      background: theme === 'light' ? '#fff' : '#333',
      color: theme === 'light' ? '#333' : '#fff'
    }}>
      主题按钮
    </button>
  );
}

// 在父组件中提供上下文值
function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}

4. useReducer:复杂状态管理

当组件状态逻辑复杂时,useReduceruseState 更合适,它通过 reducer 函数管理状态变化。

import { useReducer } from 'react';

// 定义reducer函数
function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, { id: Date.now(), text: action.text, done: false }];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.id ? { ...todo, done: !todo.done } : todo
      );
    default:
      return state;
  }
}

function TodoList() {
  // 使用useReducer,初始状态为空数组
  const [todos, dispatch] = useReducer(todoReducer, []);
  const [text, setText] = useState('');

  const handleAdd = () => {
    if (text) {
      dispatch({ type: 'ADD_TODO', text });
      setText('');
    }
  };

  return (
    <div>
      <input
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="输入待办事项"
      />
      <button onClick={handleAdd}>添加</button>
      <ul>
        {todos.map(todo => (
          <li
            key={todo.id}
            style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
            onClick={() => dispatch({ type: 'TOGGLE_TODO', id: todo.id })}
          >
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

5. useRef:访问DOM或保存可变值

useRef 可以创建一个ref对象,用于访问DOM元素,也可以保存一个可变值,其变化不会触发组件重新渲染。

import { useRef, useEffect } from 'react';

function TextInputWithFocusButton() {
  const inputRef = useRef(null);

  const focusInput = () => {
    // 通过ref访问DOM元素并调用方法
    inputRef.current.focus();
  };

  // 保存上一次渲染时的count值
  const prevCountRef = useRef();
  const [count, setCount] = useState(0);

  useEffect(() => {
    prevCountRef.current = count;
  });
  const prevCount = prevCountRef.current;

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>聚焦输入框</button>
      <p>当前count: {count},上一次count: {prevCount}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

这些是 React 中最常用的 Hooks,合理使用它们可以让函数组件的逻辑更加清晰、易于管理和复用。此外,还有 useMemouseCallback 等用于性能优化的 Hooks,在实际开发中可以根据需求选择使用。

精彩评论(0)

0 0 举报