钩子一直在席卷世界。在本教程中,我们将查看钩子是什么以及如何使用它们。我将向您介绍一些带有React的常见钩子,并向您展示如何编写自己的钩子。到完成时,您将能够在自己的React Projects中使用钩子。
。
如果我激起了您的好奇心,让我们潜入并查看一些实际的例子。>先决条件
本教程旨在针对那些对什么是反应及其工作方式有基本了解的人。如果您是React初学者,请在此处继续进行React教程的开始。如果您想跟随示例,则应该设置一个React应用程序。最简单的方法是使用Create React App工具。为了使用此功能,您将安装节点和NPM。如果您还没有,请前往Node.js下载页面并抓住系统的最新版本(NPM与Node捆绑在一起)。另外,您可以使用版本管理器咨询我们的教程有关安装节点的教程。
>安装节点,您可以创建一个新的React应用程序:这将创建一个MyApp文件夹。更改此文件夹,然后像这样启动开发服务器:
>您的默认浏览器将打开,您会看到新的React应用程序。出于本教程的目的,您可以在位于src/app.js。
>您还可以在GitHub上找到本教程的代码,以及本教程末尾完成的代码的演示。
npx create-react-app myapp> USESTATE钩
现在让我们看一些代码。 Usestate挂钩可能是与React发货的最常见钩子。顾名思义,它允许您在函数组件中使用状态。
<span>cd myapp </span><span>npm start </span>>
考虑以下REECT类组件:
如果您与Create React App一起关注,只需将App.js的内容替换为上述内容。
>给自己一分钟以了解代码。 在构造函数中,我们在状态对象上声明名称属性,并将HandlenAmeChange函数绑定到组件实例。然后,我们有一个带有输入的表单,其值设置为this.state.name。在this.state.name中持有的值也以问候的形式输出到页面。
<span>import <span>React</span> from "react"; </span> <span>export default class ClassDemo extends React<span>.Component</span> { </span> <span>constructor(props) { </span> <span>super(props); </span> <span>this.state = { </span> <span>name: "Agata" </span> <span>}; </span> <span>this.handleNameChange = this.handleNameChange.bind(this); </span> <span>} </span> <span>handleNameChange(e) { </span> <span>this.setState({ </span> <span>name: e.target.value </span> <span>}); </span> <span>} </span> <span>render() { </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={this.state.name} </span> onChange<span>={this.handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {this.state.name}</p> </span> <span></section> </span> <span>); </span> <span>} </span><span>} </span>
用户在输入字段中键入任何内容时,称为HandleNameChange函数,该功能更新状态并因此是问候。
>现在,我们将使用Usestate Hook编写此代码的新版本。它的语法看起来像这样:
npx create-react-app myapp
调用USESTATE函数时,它返回两个项目:
请注意此功能版本和类版本之间的差异。它已经比班级版本更紧凑,更容易理解,但是他们俩都做了完全相同的事情。让我们介绍差异:
<span>cd myapp </span><span>npm start </span>
>整个类构造函数已被Usestate Hook替换,该钩仅由一条线组成。
>多个usestate钩
>但是,如果我们想在州内声明多个财产怎么办?没问题。只需使用多个呼叫来进行USESESTATE。
这是一个具有多个usestate钩子的组件的示例:
>
> useffect Hook大多数反应组件都需要执行特定操作,例如获取数据,订阅数据流或手动更改DOM。这类操作称为副作用。
<span>import <span>React</span> from "react"; </span> <span>export default class ClassDemo extends React<span>.Component</span> { </span> <span>constructor(props) { </span> <span>super(props); </span> <span>this.state = { </span> <span>name: "Agata" </span> <span>}; </span> <span>this.handleNameChange = this.handleNameChange.bind(this); </span> <span>} </span> <span>handleNameChange(e) { </span> <span>this.setState({ </span> <span>name: e.target.value </span> <span>}); </span> <span>} </span> <span>render() { </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={this.state.name} </span> onChange<span>={this.handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {this.state.name}</p> </span> <span></section> </span> <span>); </span> <span>} </span><span>} </span>> 在基于类的组件中,我们通常会将副作用代码放入componentDidmount和componentDidupdate中。这些是生命周期方法,使我们能够在正确的时间触发渲染方法。
>
这是一个简单的示例:npx create-react-app myapp
>此代码将根据状态中的内容设置文档标题。但是,当您尝试通过表单更改状态值时,什么也不会发生。要解决此问题,您需要添加另一种生命周期方法:
<span>cd myapp </span><span>npm start </span>
更新表单现在也应更新文档标题。
>让我们看看如何使用使用效果钩实现相同的逻辑。更新上面的功能组件如下:
<span>import <span>React</span> from "react"; </span> <span>export default class ClassDemo extends React<span>.Component</span> { </span> <span>constructor(props) { </span> <span>super(props); </span> <span>this.state = { </span> <span>name: "Agata" </span> <span>}; </span> <span>this.handleNameChange = this.handleNameChange.bind(this); </span> <span>} </span> <span>handleNameChange(e) { </span> <span>this.setState({ </span> <span>name: e.target.value </span> <span>}); </span> <span>} </span> <span>render() { </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={this.state.name} </span> onChange<span>={this.handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {this.state.name}</p> </span> <span></section> </span> <span>); </span> <span>} </span><span>} </span>
>只有那几行代码,我们在一个简单函数中实现了两种生命周期方法的工作。
>
<span>const [state, setState] = useState(initialState); </span>>上面的代码将显示浏览器窗口的当前分辨率。调整窗口的大小,您应该自动看到数字更新。如果您在Chrome中按
> f11,则应显示显示器的完整分辨率。我们还使用了componentWillunMount的生命周期方法来解开调整大小事件。
>让我们在挂钩版本中复制上述基于类的代码。我们需要定义第三个Usestate钩子和第二个使用效果挂钩来处理这一新功能:
<span>import <span>React, { useState }</span> from "react"; </span> <span>export default function <span>HookDemo</span>(props) { </span> <span>const [name, setName] = useState("Agata"); </span> <span>function handleNameChange(e) { </span> <span>setName(e.target.value); </span> <span>} </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={name} </span> onChange<span>={handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {name}</p> </span> <span></section> </span> <span>); </span><span>} </span>
>令人惊讶的是,该代码的此挂钩版本执行相同的操作。它更干净,更紧凑。将代码放入其自己的使用效果声明中的优点是,我们可以轻松测试它,因为代码是孤立的。
>您是否注意到我们正在此使用效果挂钩中返回功能?这是因为您在使用效果功能中返回的任何功能都将被视为清理代码。如果您不返回功能,则不会进行清理。在这种情况下,需要进行清理,因为否则您会遇到登录到浏览器控制台的错误消息,说“无法在未填充组件上执行React状态更新”。
自定义React Hooks
>现在您已经了解了Usestate和使用效果挂钩,让我向您展示一种非常酷的方法,使您的代码更加紧凑,更清洁和可重复使用,而不是我们到目前为止所取得的成就。我们将创建一个自定义挂钩
以进一步简化我们的代码。创建一个新函数,如下所示:
接下来,在组件中,您需要替换此代码:…与此:
<span>import <span>React, { useState }</span> from "react"; </span> <span>export default function <span>HookDemo</span>(props) { </span> <span>const [name, setName] = useState("Agata"); </span> <span>const [location, setLocation] = useState("Nairobi"); </span> <span>function handleNameChange(e) { </span> <span>setName(e.target.value); </span> <span>} </span> <span>function handleLocationChange(e) { </span> <span>setLocation(e.target.value); </span> <span>} </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={name} </span> onChange<span>={handleNameChange} </span> <span>/> </span> <span></section> </span> <span><section> </span> <span><label htmlFor="location">Location</label> </span> <span><input </span> type<span>="text" </span> name<span>="location" </span> id<span>="location" </span> value<span>={location} </span> onChange<span>={handleLocationChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p> </span> <span>Hello {name} from {location} </span> <span></p> </span> <span></section> </span> <span>); </span><span>} </span>删除第二个使用效果代码。保存文件并测试。一切都应该像以前一样起作用。
>现在我们创建了第一个自定义挂钩,让我们为文档标题做同样的事情。首先,删除剩余的调用以在组件内的使用效果。然后,在组件之外,添加以下代码:
>npx create-react-app myapp
最后,从组件中调用它:
<span>cd myapp </span><span>npm start </span>
>返回到您的浏览器,然后将某些内容输入输入字段。文档标题应该像以前一样更改。
最后,让我们重构表单字段。我们想创建一个挂钩,以使其值与状态中的相应值保持同步。>让我们从自定义挂钩开始。添加组件的以下外部:
然后更新组件以使用它:
<span>import <span>React</span> from "react"; </span> <span>export default class ClassDemo extends React<span>.Component</span> { </span> <span>constructor(props) { </span> <span>super(props); </span> <span>this.state = { </span> <span>name: "Agata" </span> <span>}; </span> <span>this.handleNameChange = this.handleNameChange.bind(this); </span> <span>} </span> <span>handleNameChange(e) { </span> <span>this.setState({ </span> <span>name: e.target.value </span> <span>}); </span> <span>} </span> <span>render() { </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={this.state.name} </span> onChange<span>={this.handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {this.state.name}</p> </span> <span></section> </span> <span>); </span> <span>} </span><span>} </span>
>慢慢浏览代码,并确定我们所做的所有更改。很整洁,对吧?我们的组件要紧凑得多。
<span>const [state, setState] = useState(initialState); </span>为了本教程的目的,我们一直将钩子声明为与使用它们的组件相同的文件中的函数。但是,在一个普通的React项目中,您将在单独的文件中使用每个挂钩的挂钩文件夹,然后可以将其导入所需的任何地方。
>我们甚至可以将UseFormInput,underOcumentTitle和useWindowResolution钩打包到外部NPM模块中,因为它们完全独立于我们代码的主要逻辑。我们可以轻松地在项目的其他部分,甚至将来其他项目重复使用这些自定义钩子。
供参考,这是完整的挂钩组件版本:
钩的组件应呈现和表现与类组件版本完全一样:
<span>import <span>React, { useState }</span> from "react"; </span> <span>export default function <span>HookDemo</span>(props) { </span> <span>const [name, setName] = useState("Agata"); </span> <span>function handleNameChange(e) { </span> <span>setName(e.target.value); </span> <span>} </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={name} </span> onChange<span>={handleNameChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p>Hello {name}</p> </span> <span></section> </span> <span>); </span><span>} </span>如果将挂钩版本与类组件版本进行比较,则会意识到挂钩功能将组件代码降低至少30%。您甚至可以通过将可重复使用的功能导出到NPM库来进一步降低代码。
接下来,让我们看一下如何在代码中使用其他人的钩子。
>让我们看一个示例,说明如何使用Axios从REST JSON API中获取数据并进行React Hooks获取数据。如果您在家中关注,则需要安装Axios库:
更改您的组件看起来像这样:
<span>import <span>React, { useState }</span> from "react"; </span> <span>export default function <span>HookDemo</span>(props) { </span> <span>const [name, setName] = useState("Agata"); </span> <span>const [location, setLocation] = useState("Nairobi"); </span> <span>function handleNameChange(e) { </span> <span>setName(e.target.value); </span> <span>} </span> <span>function handleLocationChange(e) { </span> <span>setLocation(e.target.value); </span> <span>} </span> <span>return ( </span> <span><section> </span> <span><form autoComplete="off"> </span> <span><section> </span> <span><label htmlFor="name">Name</label> </span> <span><input </span> type<span>="text" </span> name<span>="name" </span> id<span>="name" </span> value<span>={name} </span> onChange<span>={handleNameChange} </span> <span>/> </span> <span></section> </span> <span><section> </span> <span><label htmlFor="location">Location</label> </span> <span><input </span> type<span>="text" </span> name<span>="location" </span> id<span>="location" </span> value<span>={location} </span> onChange<span>={handleLocationChange} </span> <span>/> </span> <span></section> </span> <span></form> </span> <span><p> </span> <span>Hello {name} from {location} </span> <span></p> </span> <span></section> </span> <span>); </span><span>} </span>
>可以通过构建自己的自定义钩子来重构上述代码,例如我们不再需要使用USESTATE和使用效果挂钩。对我们来说幸运的是,许多开发人员已经完成了这一任务,并发布了我们可以在项目中安装的包装的工作。我们将使用Simone Busoli的Axios-Hooks,这恰好是最受欢迎的。
您可以使用命令安装软件包:<span>componentDidMount() { </span> <span>document.title = this.state.name + " from " + this.state.location; </span><span>} </span>
npx create-react-app myapp
>下面,我使用Axios-Hooks重构上述代码:
<span>cd myapp </span><span>npm start </span>>我们不仅摆脱了代码中的Usestate和使用效果挂钩,而且我们还获得了三个新能力,没有额外的大脑功率:
显示加载状态
demo
这些是您在日常的反应项目中会遇到的基本反应挂钩:
>使用效果:替换生命周期功能
> USECALLBACK:返回一个返回可缓存值的函数。如果您想在输入没有更改时防止不必要的重新租用器,则对于性能优化很有用。
npx create-react-app myapp
您需要使用NPM或这样的纱线安装局部存储挂钩才能使用它:
<span>cd myapp </span><span>npm start </span>
很好,对吗?
引入React Hooks引起了很大的飞溅。它的海浪已超越了React社区进入JavaScript世界。这是因为钩子是一个可以使整个JavaScript生态系统受益的新概念。实际上,vue.js团队最近发布了类似的作品API。
也有关于React Hooks和上下文API从其州管理王位推翻Redux的讨论。显然,挂钩使编码变得更加简单,并改变了我们编写新代码的方式。如果您像我一样,您可能有强烈的冲动重写所有React组件类,并用功能性组件挂钩替换它们。>请注意,这并不是真正的必要:React团队不打算贬低React类组件。您还应该意识到,并非所有反应类生命周期方法都可以使用钩子。您可能必须坚持使用React组件类别更长的时间。
>如果您对基本反应钩的新知识充满信心,我想给您带来挑战。重构此倒数计时器类使用React钩子,使其尽可能清洁和紧凑。
愉快的编码,让我知道您如何进行!> REECT HOCKS上的FAQ
>
为什么引入了React Hooks?引入了React钩子,以简化功能组件中状态逻辑的重复使用,从而更容易管理组件状态和副作用。钩?
>您可以使用USESTATE挂钩将状态添加到功能组件中。它返回具有当前状态值的数组和更新它的功能。使用效果挂钩允许您在功能组件中执行副作用,例如数据获取,DOM操纵等,并确保正确处理这些效果。
>我可以使用多个>单个组件中的USESTATE和使用效果挂钩?
是的,您可以在单个功能组件中使用多个Usestate和使用效果钩的实例来管理不同的状态和效果。>用户挂钩是用于更复杂状态管理的Usestate的替代方法。当您需要以可预测的方式管理状态转换时,这很有用。
您可以通过定义使用内置钩或其他自定义钩的功能来创建自定义钩。这些自定义挂钩可以跨组件封装并共享状态逻辑。>在React中使用钩子的规则是什么?
使用挂钩的关键规则仅包括在功能组件中使用它们,使用顶层的钩子(不是内部环或条件),并确保它们在组件中的顺序在重新租用器上保持一致。> React钩有任何性能考虑吗?
正确使用时,React钩子可以通过减少不必要的重新租赁来提高性能。但是,必须使用USEMEMO和USECALLBACK挂钩在需要时优化性能。以上是React Hooks:如何开始并建立自己的的详细内容。更多信息请关注PHP中文网其他相关文章!