Skip to content

Hooks 基础(useState / useEffect)

React 基础速成

Hooks 是 React 16.8 引入的新特性,它允许我们在函数组件中使用状态和其他 React 特性。在 React Native 中,Hooks 已经成为管理状态和副作用的标准方式。

1. 什么是 Hooks?

Hooks 是一些特殊的函数,它们允许你在函数组件中使用 React 的状态和生命周期特性。

为什么使用 Hooks?

  • 函数组件更简洁:Hooks 允许我们使用函数组件而不是类组件
  • 逻辑复用:Hooks 使我们能够在不同组件之间复用状态逻辑
  • 更好的代码组织:Hooks 允许我们按功能组织代码,而不是按生命周期方法
  • 更容易理解:Hooks 使代码更线性,更容易理解

2. useState Hook

useState 是最基本的 Hook,它允许我们在函数组件中管理状态。

基本语法

jsx
import { useState } from 'react';

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

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

在 React Native 中的使用:

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <View>
      <Text>You clicked {count} times</Text>
      <Button 
        title="Click me" 
        onPress={() => setCount(count + 1)} 
      />
    </View>
  );
}

状态更新

基本更新

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

// 基本更新
setCount(count + 1);

函数式更新

当新的状态依赖于旧的状态时,应该使用函数式更新:

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

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

批量更新

React 会批量处理状态更新,这意味着多个 setState 调用会在一次渲染中完成:

jsx
const [name, setName] = useState('');
const [age, setAge] = useState(0);

const updateUser = () => {
  // 这两个更新会被批量处理
  setName('John');
  setAge(30);
};

3. useEffect Hook

useEffect 是另一个常用的 Hook,它允许我们在函数组件中执行副作用操作。

基本语法

jsx
import { useEffect } from 'react';

function Example() {
  useEffect(() => {
    // 副作用代码
    console.log('Component mounted');

    // 清理函数
    return () => {
      console.log('Component unmounted');
    };
  }, []); // 依赖数组

  return <div>Example</div>;
}

在 React Native 中的使用:

jsx
import { View, Text } from 'react-native';
import { useEffect } from 'react';

export default function Example() {
  useEffect(() => {
    console.log('Component mounted');

    return () => {
      console.log('Component unmounted');
    };
  }, []);

  return (
    <View>
      <Text>Example</Text>
    </View>
  );
}

依赖数组

useEffect 接受第二个参数,一个依赖数组,用于控制副作用的执行时机:

空依赖数组

当依赖数组为空时,副作用只会在组件挂载时执行一次:

jsx
useEffect(() => {
  // 只在组件挂载时执行
  console.log('Component mounted');
}, []);

依赖项

当依赖数组包含值时,副作用会在依赖项变化时执行:

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

useEffect(() => {
  // 当 count 变化时执行
  console.log(`Count changed to: ${count}`);
}, [count]);

没有依赖数组

当没有依赖数组时,副作用会在每次渲染后执行:

jsx
useEffect(() => {
  // 在每次渲染后执行
  console.log('Component re-rendered');
});

4. 自定义 Hook

我们可以创建自己的自定义 Hook 来复用状态逻辑。

基本语法

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

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  const decrement = () => {
    setCount(prevCount => prevCount - 1);
  };

  const reset = () => {
    setCount(initialValue);
  };

  return { count, increment, decrement, reset };
}

// 使用自定义 Hook
function Counter() {
  const { count, increment, decrement, reset } = useCounter(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

在 React Native 中的使用:

jsx
import { View, Text, Button } from 'react-native';
import { useState, useEffect } from 'react';

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  const decrement = () => {
    setCount(prevCount => prevCount - 1);
  };

  const reset = () => {
    setCount(initialValue);
  };

  return { count, increment, decrement, reset };
}

export default function Counter() {
  const { count, increment, decrement, reset } = useCounter(0);

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
      <Button title="Decrement" onPress={decrement} />
      <Button title="Reset" onPress={reset} />
    </View>
  );
}

5. 常见错误与解决方案

错误 1:在条件语句中使用 Hook

错误

jsx
import { useState } from 'react';

function Counter() {
  if (true) {
    const [count, setCount] = useState(0); // 错误:在条件语句中使用 Hook
  }

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

解决方案

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 正确:在组件顶部使用 Hook

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

错误 2:在循环中使用 Hook

错误

jsx
import { useState } from 'react';

function Counter() {
  for (let i = 0; i < 5; i++) {
    const [count, setCount] = useState(0); // 错误:在循环中使用 Hook
  }

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

解决方案

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 正确:在组件顶部使用 Hook

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

错误 3:在嵌套函数中使用 Hook

错误

jsx
import { useState } from 'react';

function Counter() {
  function innerFunction() {
    const [count, setCount] = useState(0); // 错误:在嵌套函数中使用 Hook
  }

  innerFunction();

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

解决方案

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 正确:在组件顶部使用 Hook

  function innerFunction() {
    // 可以使用 count 和 setCount
  }

  innerFunction();

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
}

6. 最佳实践

1. 只在需要时使用 Hook

  • 只在函数组件的顶部使用 Hook
  • 不要在条件语句、循环或嵌套函数中使用 Hook
  • 确保 Hook 的调用顺序在每次渲染中保持一致

2. 合理使用依赖数组

  • 对于只需要执行一次的副作用,使用空依赖数组
  • 对于依赖于特定值的副作用,将这些值添加到依赖数组中
  • 避免使用空依赖数组时引用可能变化的值

3. 自定义 Hook 命名

  • 自定义 Hook 应该以 use 开头
  • 使用描述性的名称,反映 Hook 的功能

4. 状态管理

  • 对于简单的状态,使用 useState
  • 对于复杂的状态,考虑使用 useReducer
  • 对于跨组件共享的状态,使用 Context API

5. 性能优化

  • 使用 useCallback 缓存函数
  • 使用 useMemo 缓存计算结果
  • 使用 useRef 存储不需要触发重新渲染的值

7. 总结

Hooks 是 React 和 React Native 中管理状态和副作用的强大工具:

  • useState:用于管理组件的状态
  • useEffect:用于执行副作用操作
  • 自定义 Hook:用于复用状态逻辑

掌握 Hooks,你可以创建出更加简洁、可维护的 React Native 应用。

在使用 Hooks 时,要注意:

  1. 只在函数组件的顶部使用 Hook
  2. 合理使用依赖数组
  3. 遵循 Hook 的命名约定
  4. 注意性能优化

至此,我们已经完成了 React 基础的学习。在接下来的教程中,我们将开始学习 React Native 的核心基础,包括核心组件、样式和布局等。

© 2026 编程马·菜鸟教程 版权所有