返回

揭开 React Hooks useState 的面纱:直接和间接数据变更的博弈

前端





**在 React 组件中巧用 useState 实现数据管理的艺术** 

在 React 应用程序中,管理组件的内部数据是至关重要的,而 useState 就是帮助我们轻松搞定此项工作的秘密武器。有了它,我们可以轻松定义组件内部的状态,并进而渲染出响应式 UI。

**useState 的本质与用法** 

useState 接受一个初始 state 值,并为组件提供一个数组。数组的第一个值就是我们定义的状态,而第二个值则是一个用于变更此 state 的方法。值得注意的是,useState 仅限于在**"基于类"组件和"非类(或称‘Function’)组件** 中使用。

在"基于类"组件中,我们可以这样使用 useState:

```js
import React, { useState } from 'react';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    // 组件 state 的初始值
    const [count, setCount] = useState(0);

    this.setState({ count });
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>+</button>
      </div>
    );
  }

  incrementCount() {
    this.setState(prevState => {
      return { count: prevState.count + 1 };
    });
  }
}

export default MyComponent;

而到了"非类"组件中,useState 的用法就更为简洁了:

import React, { useState } from 'react';

function MyComponent() {
  // 组件 state 的初始值
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(prevState => prevState + 1);
  };

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

export default MyComponent;

直接与间接数据变更:孰优孰劣?

直接数据变更:

setCount(newState);

间接数据变更(使用回调):

setCount(prevState => {
  // 根据前一个 state 计算出新 state
  const newState = calculateNewState(prevState);
  return newState;
});

直接数据变更,顾名思义,就是直接调用 setCount() 方法来替换原有的 state。而间接数据变更则更加灵活,它允许我们在变更 state 逻辑中访问到前一个 state,以便于基于其进行计算并生成新 state。

何种场景下使用直接数据变更?

  • 当新 state 直接可得,无需基于前一个 state 进行计算时。
  • 当需要快速浅层数据变更时(例如,布尔值翻转或数组追加/移除单一 元素时。

何时使用间接数据变更(带回调)?

  • 当新 state 涉及到基于前一个 state 的复杂计算时。
  • 当新 state 涉及到复杂的嵌套对象的深层复制或合并时。
  • 当需要确保 state 的变更满足特定规则或限制时。

示例:使用 Hooks 重构一个 Class 组件

// 原 Class 组件
class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      count: 0
    };
  }

  incrementCount = () => {
    this.setState(prevState => {
      return { count: prevState.count + 1 };
    });
  };

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.incrementCount}>+</button>
      </div>
    );
  }
}

// 使用 Hooks 重构后的非类组件
function MyComponent() {
  const [count, setCount] = useState(0);

  const incrementCount = () => {
    setCount(prevState => prevState + 1);
  };

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

使用 useState 的最佳实战

  1. 始终遵循"单一职责"和"数据流"的准则,确保组件的 state 易于管理且易于调试。
  2. 谨慎使用直接数据变更,因为它可能导致意外的副作用,尤其是当涉及到复杂 state 对象时。
  3. 充分运用间接数据变更(带回调)来管理复杂 state,因为它更灵活,并且有助于避免意外的变更。
  4. 考虑使用 immer.js 等库来简化 state 的深层变更,以防不慎使用不当的嵌套 state。
  5. 善于为 state 的每个部分使用独立的 useState() 调用,以提高可读性、可调试性和模块化。

总结

掌握 useState 的奥义将助你如虎添翼,高效驾驭 React 组件的状态管理。谨记直接与间接数据变更的适用场景,灵活运用,便能轻松应对复杂多变的 state 管理需求。愿你用 useState 的魔法棒,挥洒出精彩纷呈的 React 组件!