在 React 中创建一个自定义 Hook
我们完成了!
大家好👋
休息了好一会儿,我们又回来了,React 系列的另一篇文章,里面有两篇关于 Hook 的精彩文章。如果你是从参考资料里偶然发现这篇文章的,但又不知道 Hook 是什么,我强烈建议你先看看链接里的那两篇文章,我们在这两篇文章里深入讨论了React 中的常用 Hook以及一些必要的基础 Hook。
在本文中,我们将解释如何在 React 中创建自定义钩子。因为以这种方式使用 React,可能会真正改变你开发组件的方式 😉 所以首先,什么是钩子?嗯,答案就在这里😄。所以我们跳过这部分,直接跳到下一步。
没有自定义钩子
假设我们的组件中有一个功能,当用户调整屏幕大小时,获取窗口的宽度。我们需要知道屏幕是小、中还是大。
我们可以这样写:
const LayoutComponent = () => {
const [onSmallScreen, setOnSmallScreen] = useState(false)
useEffect(() => {
checkScreenSize();
window.addEventListener("resize", checkScreenSize);
}, []);
let checkScreenSize = () => {
setOnSmallScreen(window.innerWidth < 700);
};
return (
<div className={`${onSmallScreen ? "small" : "large"}`}>
<h1>Hello from Default Hooks</h1>
</div>
);
};
问题
这个组件运行正常。根据宽度小于 700,它就能判断尺寸。但是,想象一下,如果我需要在其他组件中检查相同的屏幕尺寸,该怎么办?我应该复制粘贴代码吗?当然可以!但这会破坏 React 代码的可复用性。我们可以将此功能提取到一个自定义钩子中,并在任何需要的地方复用它。💯
创建自定义钩子
因为钩子只是 JS 函数,所以它们不需要 React 组件实际存在。
我将创建一个名为useWindowsWidth.js的新文件:
import { useState, useEffect } from "react";
const useWindowsWidth = () => {
const [isScreenSmall, setIsScreenSmall] = useState(false);
let checkScreenSize = () => {
setIsScreenSmall(window.innerWidth < 700);
};
useEffect(() => {
checkScreenSize();
window.addEventListener("resize", checkScreenSize);
//Cleanup
return () => window.removeEventListener("resize", checkScreenSize);
}, []);
return isSreenSmall;
};
export default useWindowsWidth;
使用钩子
我们将此功能提取到了 useWindowsWidth 函数中。现在,我们可以在任何需要的地方导入它了!
import React from "react"
import useWindowsWidth from "./useWindowsWidth.js"
const MyComponent = () => {
const onSmallScreen = useWindowsWidth();
return (
//Return some element
)
}
现在,无论我需要什么屏幕尺寸,都可以使用 useWindowsWidth()。是不是很酷?比如,你不用从头写整段代码,只需导入这个函数即可。你甚至可以使用 props 让这段代码更具动态性,只需将硬编码的屏幕尺寸替换成this.props.screenSizeCheck
woosh!你可以在任何需要的地方重复使用这个组件,并且设置任意尺寸。
常问问题
我们的自定义钩子名称是否必须以“use”开头?
是的!根据React 官方文档:
与 React 组件不同,自定义 Hook 不需要特定的签名。我们可以决定它接受什么参数,以及它应该返回什么(如果有的话)。换句话说,它就像一个普通的函数。它的名称应该始终以 use 开头,这样你一眼就能看出它符合 Hook 的规则。
两个组件中的相同自定义钩子是否共享状态?
没关系!放心吧。如果你在两个组件中使用相同的自定义钩子,它们将不会共享状态。
我们完成了!
自定义 hooks 让你在编写 React 代码时真正发挥你的想象力。你可以以一种类组件无法实现的方式提取和共享逻辑 😄。没错,这也让我们能够创建非常“实用”的函数,可以在应用程序的不同位置使用。
不知道你有没有注意到这里的文字游戏。😉