2022 年 React Hooks 最佳实践

2025-05-25

2022 年 React Hooks 最佳实践

基于类的组件以前可以访问 React 的功能,例如状态和生命周期函数。因此,基于函数的组件被称为“瘦组件,或纯展示组件”,因为它们无法访问状态和生命周期函数。

自 React Hooks 发布以来,基于函数的组件已成为 React 的一等公民。此外,一些公司还提供 React 开发服务,并聘请专门的 React 开发人员,在整个开发过程中为您提供帮助。函数组件的出现,使得编写、重用和共享 React 代码的新方法成为可能。

钩子的简单示例

import React, { useState } from 'react';

function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);

return (
<div>

You clicked {count} times

<button> setCount(count + 1)}
Click me
</button>

</div>
);
}
Enter fullscreen mode Exit fullscreen mode

输出:

图片描述
单击后您将获得如下输出:

图片描述
在本文中,我们将为您提供在组件中使用 React Hooks 的六种策略:

1. 遵守 Hooks 的规定

尽管这看起来是不言而喻的,但新手和经验丰富的 React 开发人员在使用 React hooks 时常常无法遵守以下准则:

A. 在最高层调用钩子

避免使用循环、嵌套函数和条件语句来编写钩子。在钩子内部,添加您希望应用于应用程序的条件。

不应该这样做:

if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}
Instead, do this:


useEffect(function persistForm() {
if (name !== '') {
localStorage.setItem('formData', name);
}
});
Enter fullscreen mode Exit fullscreen mode

由于此规则,所有 Hook 在组件渲染时都会被顺序调用。React 之所以能够做到这一点,是因为 useState 和 use effect 函数能够恰当地保存 Hook 的状态。

B. 仅从函数组件调用钩子
常规 JavaScript 函数不应调用钩子。函数组件或自定义钩子只能用于在应用程序中调用钩子。

该规则确保遵循该规则,组件中的每个状态逻辑都可以在源代码中轻松看到。

2. React Hooks 可能会受益于 ESLint 插件

React 团队开发了一个用于 React Hooks 的 ESLint 插件,名为 eslint-plugin-react。在开始执行应用程序之前,此插件会检测并纠正 hooks 问题。

它有两个简单的规则:

react-hooks/rules-of-hooks
react-hooks/exhaustive-deps
第一条规则只是强制你的代码遵循 hooks 的要求。为了确保 useEffect 的规则得到遵守,我们使用了 exhaustive-deps 规则。

以下 userInfo 组件可能会触发 Exhaustive-deps 警告,因为 useEffect 使用了 userId 变量,但它没有出现在依赖项数组中

React-hooks/hooks 规则:

function Form() {
// 1. Use the accountName state variable
const [accountName, setAccountName] = useState('David');

// 2. Use an effect for persisting the form
useEffect(function persistForm() {
localStorage.setItem('formData', accountName);
});

// 3. Use the accountDetail state variable
const [accountDetail, setAccountDetail] = useState('Active');

// 4. Use an effect for updating the title
useEffect(function updateStatus() {
document.title = accountName + ' ' + accountDetail;
});

}
React-hooks/exhaustive-deps:

import React, { useState } from "react";
import ReactDOM from "react-dom";

function Account(props) {
    const [name, setName] = useState("David");
    return;
Hello, {name}! The price is {props.total} and the total amount is {props.amount}
} ReactDOM.render( , document.getElementById('root') );
Enter fullscreen mode Exit fullscreen mode

图片描述

3. 按顺序构建功能组件至关重要。

为了充分利用 React 应用程序,在创建类组件时遵循特定规则非常重要。

调用 Object() { [原生代码] } 函数并启动状态后,就可以开始使用了。接下来是组件的任务相关函数,然后是生命周期函数。完成后,你需要

创建渲染方法。

import React, { useState } from 'react';
const propTypes = {
    id: propTypes.number.isRequired,
    url: propTypes.string.isRequired,
    text: propTypes.string,
};

const defaultProps = {
    text: 'Hello World',
};
class Link extends React.Component {
    static methodsAreOk() {
        return true;
    }
    constructor(props) {
        super(props)
        this.state = {
            user: null
        }
    }

    componentDidMount() {
        console.log('component did mount')
    }
    componentDidUpdate() {
        console.log('component did update')
    }
    componentWillUnmount() {
        console.log('component will unmount')
    }
    render() {
        return {this.props.text}
    }
}
Link.propTypes = propTypes
Link.defaultProps = defaultProps
export default Link;
Enter fullscreen mode Exit fullscreen mode

类组件具有内置函数 Object() { [本机代码] } 和生命周期函数,但是函数组件不具备以下功能:

function App() {
const [user, setUser] = useState(null);
useEffect(() => {
console.log("component is mounted");
}, []);
const [name, setName] = useState('');
return
<h1>React component order</h1>
;
}
Enter fullscreen mode Exit fullscreen mode

与类组件一样,函数组件的结构也必须清晰。声明状态变量并设置订阅后,就可以使用 useEffect hook 编写任何合适的函数了。

最后,您应该将渲染的组件发送回浏览器:

function App() {
const [user, setUser] = useState(null);
const [name, setName] = useState('');
useEffect(() => {
console.log("component is mounted");
}, []);
return
<h1>React component order</h1>
;
}
Enter fullscreen mode Exit fullscreen mode

如果您强制执行逻辑结构,您的代码将更易于阅读和理解。

4. UseState 的作用与类组件的状态相同

在许多 useState 示例中,为每个状态声明多个变量是常见的做法。

const [name, setName] = useState('Liam Walker');
const [email, setEmail] = useState('liamwalker@email.com');
const [age, setAge] = useState(24);
Enter fullscreen mode Exit fullscreen mode

但是 useState 可以同时包含数组和对象。仍然可以将相关信息安排在一起,例如以下示例:

const [user, setUser] = useState(
{ name: 'Liam', email: 'liamwalker07@email.com', age: 24 }
);
Enter fullscreen mode Exit fullscreen mode

然而,有一个问题。当使用 useState 的更新函数更新状态时,旧状态会被移除,并改用新状态。这与类组件的 this 不同。在 setState 中,新状态会与旧状态合并。

const [user, setUser] = useState(
{ name: 'Liam', email: 'liamwalker07@email.com', age: 24 }
);
setUser({ name: 'Lucas' });
// result { name: 'Lucas' }
Enter fullscreen mode Exit fullscreen mode

为了维护先前的状态,你需要手动合并它,方法是实现一个回调函数,将当前状态值发送给回调函数。鉴于上例中 user 变量作为状态值,以下参数可以发送给 setUser 函数:

setUser((user) => ({ ...user, name: 'Lucas' }));
// result is { name:'Lucas', email: 'liamwalker@email.com', age: 24 }
Enter fullscreen mode Exit fullscreen mode

根据应用程序数据变化的频率,将状态分解为多个变量是一个好主意。

根据经验法则,最好将每个州分开,以便于更新和提交数据。

5. 通过一次 API 调用来平衡多个 useState 请求

自定义钩子可用于跨应用程序共享功能。

在创建程序时,部分应用程序逻辑将在多个组件之间重复使用。

自定义钩子允许您将组件的功能分离为可重用的函数,如下一篇关于 React Hooks 的文章中所述。

您可以使用 Bit (Github) 将钩子发布到单个精选集合。使用此方法,您可以在许多应用中安装和重复使用它们。无需新建一个“钩子库”项目——您只需将任何项目中的新钩子“推送”到您的共享集合即可。

Hook 不能在类组件中使用,这是该技术的主要缺点。如果你仍在项目中使用旧的类组件,可以考虑以下几种方案:你可以将这些组件转换为函数,或者使用其他可复用的逻辑模式(例如 HOC 或 Render Props)。

6.避免使用道具钻孔

在 React 应用中,不断将数据从一个父组件传递到另一个父组件,直到到达相应的子组件,这被称为上下文 prop 钻取。其他嵌套组件实际上并不需要它们。

使用 React Context,无需手动在组件之间提供 props,即可通过组件树向下传递数据。useContext 钩子允许子组件使用父组件的 React Context 属性。

结论:

这是 React 框架的一项出色补充,它允许你以前所未有的方式编写、重用和共享 React 代码。由于 Hook 改变了开发人员构建 React 组件的方式,因此需要构建 React Hook 的新最佳实践,以促进跨团队的开发和协作。

感谢您阅读我们的文章。希望您喜欢这篇文章。请与我们分享您的想法,并告诉我们您的疑问,我们随时为您解决问题。

此外,Bosc Tech 拥有一支 React 专家团队。如有任何 React 开发方面的需求,请联系我们。请告诉我们您的疑问!

文章来源:https://dev.to/kuldeeptarapara/react-hooks-best-practices-in-2022-4bh0
PREV
哦,你好,Apollo Client,再见,Redux!
NEXT
Spring Security 与 JWT