🔥 使用React时要避免的 10 大错误

2,595 阅读6分钟

本片文章主要讨论React开发最常犯的10个错误---以及如何解决这些错误。

我们主要介绍一下10个最常见的错误:

  1. 没有拆分创建组件
  2. 直接修改state的状态
  3. 传递props时将数字作为字符串传递
  4. 不在循环列表时使用key
  5. 忘记setState是异步方法
  6. 过度使用 Redux
  7. 不拆分组件,所有的UI和业务逻辑都在一个组件中
  8. 不遵循React的文件结构
  9. 将props作为String发送,而不是Number
  10. 忘记以大写字母作为组件的名称开头

没有拆分创建组件

在书写React时,最常犯的错误就是没有及时拆分组件,使用React你可创建大型的组件应用于许多任务, 但是最好保持组件的代码量较少,一个组件对应一个功能,这样不仅可以节省我们的时间,也有助于我们调试代码,因为组件足够小,所以更加方便我们调试代码,找到BUG!!

我们来看一个TodoList组件的例子:

// TodoList.jsx

import React from "react";
import { useTodoList } from "../hooks/useTodoList";
import { useQuery } from "../hooks/useQuery";
import TodoItem from "./TodoItem";
import NewTodo from "./NewTodo";

const TodoList = () => {
  const { getQuery, setQuery } = useQuery();
  const todos = useTodoList();
  return (
    <div>
      <ul>
        {todos.map(({ id, title, completed }) => (
          <TodoItem key={id} id={id} title={title} completed={completed} />
        ))}
        <NewTodo />
      </ul>
      <div>
        Highlight Query for incomplete items:
        <input value={getQuery()} onChange={(e) => setQuery(e.target.value)} />
      </div>
    </div>
  );
};

export default TodoList;

直接修改state的状态

在React中,state是不应该直接被改变的 如果你直接修改了state,会导致难以修复的性能问题,并且页面也不会更新你所修改的值!

我们来看一个不好的例子:

const modifyPetsList = (element, index) => { 
  petsList[index].checked = element.target.checked; 
  setPetsList(petsList); 
};

这个例子想根据复选框的状态来更新数据对应的checked属性,如果这样就会遇到页面无法更新状态,尽管数据被更改正确,导致这种情况的出现是因为petsList的引用没有发生改变,所以React无法观察和触发重新渲染。

要解决这个问题,可以使用setState()或者useState()钩子函数,这两种方法中的任何一种都将确保我们的更改被 React 确认并且 DOM 被正确重新渲染。

注意: 我们还可以使用map()和spread syntax来避免改变其他状态值。

const modifyPetsList = (element, id) => { 
  const {checked } = element.target; 
  setpetsList((pets) => { 
    return pets.map((pet, index) => { 
      if (id === index) { 
        pet = { ...pet, checked }; 
      } 
      return pet; 
    }); 
  }) ; 
};

传递props时将数字作为字符串传递

在传递 props 时将数字作为字符串传递可能会导致React 程序出现问题。

请看下面的例子:

class Arrival extends React.Component {
  render() {
    return (
      <h1>
        Hi! You arrived {this.props.position === 1 ? "first!" : "last!"} .
      </h1>
    );
  }
}

在这个例子中 this.props.position 期望获得一个数字,由于我们使用的是严格比较,所以任何不是数字或不完全等于1的值都会触发 'last' 这个值。

要解决这个问题我们应该这样写:

const element = <Arrival position={1} />;

不在循环列表时使用key

假设我们要在页面上呈现一个列表,代码如下:

const lists = ['cat', 'dog', 'fish’];

render() {
  return (
    <ul>
      {lists.map(listNo =>
        <li>{listNo}</li>)}
    </ul>
  );
}

如果这段代码不涉及元素的正删改查,这可能会奏效。但是在大型列表时,如果想对该列表进行正删改查就会遇到渲染问题。

React 跟踪文档对象模型 (DOM) 上的所有列表元素。如果没有这个记录,React 不会知道你的列表中发生了什么变化。

要解决此问题,您需要为所有列表元素添加key。key给每个元素一个唯一的标识,这有助于 React 确定哪些项目已被添加、删除、修改等。

<ul> 
  {lists.map(listNo => 
    <li key={listNo}>{listNo}</li>)} 
</ul>

忘记setState是异步方法

很容易忘记React中的状态是异步的。即使是最有经验的 React 开发人员也会忘记这一点。

异步意味着我们所做的任何修改不会立即生效(并且可能会在下一次渲染时生效)React 自动批量更新调用以提高性能。如果我们在设置状态值后立即访问它,可能无法获得最准确的结果。

看如下代码:

handlePetsUpdate = (petCount) => {
  this.setState({ petCount });
  this.props.callback(this.state.petCount); // Old value
};

我们可以通过为 setState() 提供可选的第二个参数来解决此问题,该参数将充当回调函数。使用更改更新状态后,将立即调用回调函数。

handlePetsUpdate = (petCount) => {
  this.setState({ petCount }, () => {
    this.props.callback(this.state.petCount); // Updated value
  });
};

注意:同样的事情也适用于useState(),除了它们没有与 setState() 类似的回调参数。相反,您将使用useEffect()钩子来获得相同的结果。

过度使用 Redux

对于更大的 React 应用程序,许多开发人员使用 Redux 来管理全局状态。

尽管 Redux 很有用,但您无需使用它来管理应用程序中的每个状态。

如果我们的应用没有任何需要交换信息的并行级组件,则无需向项目添加额外的库。当我们使用表单组件并希望在每次访问时检查检查按钮的状态时,建议使用本地状态useState方法或Redux。

不拆分组件,所有的UI和业务逻辑都在一个组件中

这种组件是整体式的,不可重复使用

它们在 React 中被称为“反模式”。我们不应该构建一个将所有 UI 元素塞进一个组件中的整个页面。相反,我们应该花时间概述应用程序的不同互连部分,并使它们成为自己的组件。当我们以这种方式分离组件时,应用程序的所有部分都更容易在需要时进行维护和重组。

不遵循React的文件结构

我们创建的项目不仅仅用于当前的开发。它们很可能在未来需要维护或操纵。在考虑项目的未来可能性时,文件夹结构非常重要。

我们来看看 ReactJS 社区遵循的标准文件夹结构:

image.png

在导航到任何现有项目时,为容器、资产和组件设置单独的位置很有用。遵循命名约定以帮助提高可读性和组织性也很有用。这有助于我们轻松识别项目中编写的任何代码的用途。

将props作为String发送,而不是Number

具有编写大量 HTML 经验的 React 开发人员发现编写如下内容很自然:

<MyComponent value="4" />

这个value props实际上将作为字符串发送到 MyComponent。如果我们确实需要将其作为数字,则可以通过使用类似parseInt()函数或插入大括号而不是引号来解决此问题。

<MyComponent value={4} />

忘记以大写字母作为组件的名称开头

记以大写字母开头组件名称是一个很容易犯的小错误。在 JSX 中,以小写字母开头的组件编译为 HTML 元素。

假如我们写了如下代码:

class demoComponentName extends React.Component {
   
}

这会导致一个错误,告诉你如果你打算渲染一个 React 组件,你需要以大写字母开头它的名称。

这个错误有一个简单的修复方法,即以大写字母开头的组件名称如下:

class DemoComponentName 扩展 React.Component { 

}

往期精彩文章

webpack打包优化方向指南(理论篇)

vue遇到拖拽动态生成组件怎么办?

javaScript编程技巧

TypeScript 它不香吗?还不快来!

下篇文章主要想写设计React组件时的5大模式,点个关注不迷路!!