2月阅读周·React设计模式与最佳实践:需要避免的反模式篇

举报
叶一一 发表于 2025/02/23 15:23:07 2025/02/23
【摘要】 引言《React设计模式与最佳实践》本书将带你全面了解React中最有价值的设计模式,并展示如何在全新或已有的真实项目中应用设计模式与最佳实践。本书将帮助你让应用变得更加灵活、运行更流畅并且更容易维护——在不降低质量的情况下极大地提升工作流的速度。本书包括以下几部分内容:React的内部原理。编写整洁且可维护的代码,即保持代码整洁并遵循编程风格指南。开发能够在整个应用中复用的组件,构建应用的...

引言

《React设计模式与最佳实践》本书将带你全面了解React中最有价值的设计模式,并展示如何在全新或已有的真实项目中应用设计模式与最佳实践。本书将帮助你让应用变得更加灵活、运行更流畅并且更容易维护——在不降低质量的情况下极大地提升工作流的速度。

本书包括以下几部分内容:

  • React的内部原理。
  • 编写整洁且可维护的代码,即保持代码整洁并遵循编程风格指南。
  • 开发能够在整个应用中复用的组件,构建应用的一个关键因素在于使用组件,而要想保持代码库整洁且可维护,最重要的是开发真正可复用的组件。
  • 搭建应用架构,并创建真正可用的表单。
  • 服务端渲染是,虽然该特性开箱即用,但学习其正确用法很重要,因为这样才能充分加以利用。
  • 提升应用性能,性能是Web平台吸引用户的重要因素之一。React提供了一系列工具和技术来创建快如闪电的应用,这一章将全面介绍这些内容。
  • 测试与调试,编写全面的测试集对于创建稳定且可维护的代码至关重要。从另一方面来看,bug总会出现,而知道如何调试并尽早发现问题很关键。

需要避免的反模式

用prop初始化状态

问题描述

在React组件中,有时会使用父组件传递的prop来初始化组件的状态。例如:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data
    };
  }

  render() {
    return <div>{this.state.data}</div>;
  }
}

问题分析

这种做法的问题在于,当父组件的data prop发生变化时,子组件的状态不会自动更新。因为React组件的状态是独立于props的,只有通过setState方法才能更新状态。

解决方案

正确的做法是直接使用props,而不是将其复制到状态中。如果需要在组件内部修改数据,可以考虑使用受控组件或使用getDerivedStateFromProps生命周期方法(在React 16.3及以上版本中)。

class MyComponent extends React.Component {
  render() {
    return <div>{this.props.data}</div>;
  }
}

修改状态

问题描述

在React中,直接修改状态是不被推荐的。例如:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  handleClick() {
    this.state.count++; // 错误的做法
    this.forceUpdate(); // 强制更新
  }

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

问题分析

直接修改状态会导致React无法检测到状态的变化,从而无法正确地更新组件。此外,使用forceUpdate方法强制更新组件会绕过React的优化机制,可能会导致性能问题。

解决方案

正确的做法是使用setState方法来更新状态。setState方法会通知React状态已经发生变化,并触发组件的重新渲染。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

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

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

将数组索引作为key

问题描述

在渲染列表时,有时会使用数组的索引作为每个列表项的key属性。例如:

const listItems = items.map((item, index) =>
  <li key={index}>{item}</li>
);

问题分析

使用数组索引作为key可能会导致性能问题和错误的行为。当列表项的顺序发生变化时,React会认为所有的列表项都发生了变化,从而重新渲染整个列表。此外,如果列表项的内容发生变化,React也无法正确地识别哪些列表项需要更新。

解决方案

正确的做法是使用唯一的标识符作为key,例如每个列表项的ID。如果列表项没有唯一的ID,可以考虑使用其他唯一的属性或生成一个唯一的ID。

const listItems = items.map(item =>
  <li key={item.id}>{item}</li>
);

在DOM元素上展开props对象

问题描述

在渲染DOM元素时,有时会将props对象展开到元素上。例如:

const MyComponent = (props) => {
  return <div {...props} />;
};

问题分析

这种做法可能会导致不必要的属性传递给DOM元素,从而增加DOM的复杂性和渲染成本。此外,如果props对象中包含一些不应该传递给DOM元素的属性,可能会导致意外的行为。

解决方案

正确的做法是只传递需要的属性给DOM元素。如果需要传递多个属性,可以使用解构赋值来提取需要的属性。

const MyComponent = ({ className, children, ...rest }) => {
  return <div className={className} {...rest}>{children}</div>;
};

总结

在React开发中,避免常见的反模式是提高代码质量和性能的关键。通过遵循最佳实践和设计模式,我们可以构建出更加高效、可维护的应用。在本文中,我们探讨了用prop初始化状态、修改状态、将数组索引作为key、在DOM元素上展开props对象等反模式,并提供了相应的解决方案。希望这些内容能够帮助你更好地理解和应用React。


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。