react hooks_在不到10分钟的时间内学习React Hooks的基础知识

react hooks

Early this year, the React team released a new addition, hooks, to React in version 16.8.0.

今年年初,React团队在版本16.8.0中向React发布了新的挂钩。

If React were a big bowl of candies, then hooks are the latest additions, very chewy candies with great taste!

如果说React是一大碗糖果,那么钩子就是最新的添加,非常有嚼劲的糖果,味道很好!

So, what exactly do hooks mean? And why are they worth your time?

那么,钩子到底是什么意思? 为什么他们值得您花时间?

介绍 (Introduction)

One of the main reasons hooks were added to React is to offer a more powerful and expressive way to write (and share) functionality between components.

向React添加钩子的主要原因之一是提供了一种更强大,更富表现力的方式来在组件之间编写(和共享)功能。

In the longer term, we expect Hooks to be the primary way people write React components — React Team

从长远来看,我们希望Hooks成为人们编写React组件的主要方式-React Team

If hooks are going to be that important, why not learn about them in a fun way!

如果钩子变得如此重要,为什么不以有趣的方式了解它们呢!

糖果碗 (The Candy Bowl)

Consider React to be a beautiful bowl of candy.

将React视为一碗漂亮的糖果。

The bowl of candy has been incredibly helpful to people around the world.

这碗糖果对世界各地的人们都有不可思议的帮助。

The people who made this bowl of candy realized that some of the candies in the bowl weren’t doing people much good.

制作这碗糖果的人意识到碗里的一些糖果对人们没有多大好处。

A couple of the candies tasted great, yes! But they brought about some complexity when people ate them — think render props and higher order components?

是的,有几个糖果尝起来很棒! 但是当人们食用它们时,它们带来了一些复杂性-想想渲染道具和高阶组件?

So, what did they do?

那么他们做了什么?

They did the right thing — not throwing away all the previous candies, but making new sets of candies.

他们做了正确的事情-不会扔掉所有以前的糖果,而是制作新的糖果。

These candies were called Hooks.

这些糖果被称为胡克斯

These candies exist for one purpose: to make it easier for you to do the things you were already doing.

这些糖果的存在是为了达到一个目的: 使您更轻松地完成自己已经在做的事情

These candies aren’t super special. In fact, as you begin to eat them you’ll realize they taste familiar — they are just Javascript functions!

这些糖果不是超级特别。 实际上,当您开始吃它们时,您会意识到它们听起来很熟悉-它们只是Javascript函数

As with all good candies, these 10 new candies all have their unique names. Though they are collectively called hooks.

与所有好的糖果一样,这10种新糖果都有其独特的名称。 虽然它们统称为钩子

Their names always begin with the three letter word, use … e.g. useState, useEffect etc.

它们的名称始终以三个字母开头, 使用…,例如useStateuseEffect等。

Just like chocolate, these 10 candies all share some of the same ingredients. Knowing how one tastes, helps you relate to the other.

就像巧克力一样,这10个糖果都共享一些相同的成分。 知道一种口味,可以帮助您与另一种相处。

Sounds fun? Now let’s have these candies.

听起来很有趣? 现在让我们吃这些糖果。

国家挂钩 (The State Hook)

As stated earlier, hooks are functions. Officially, there are 10 of them. 10 new functions that exist to make writing and sharing functionalities in your components a lot more expressive.

如前所述,钩子是函数。 官方上有10个。 现有的10个新功能使组件中的编写和共享功能更具表现力。

The first hook we’ll take a look at is called, useState.

我们将要看的第一个钩子称为useState

For a long time, you couldn’t use the local state in a functional component. Well, not until hooks.

长期以来,您无法在功能组件中使用局部状态。 好吧,直到钩上。

With useState, your functional component can have (and update) local state.

使用useState ,您的功能组件可以具有(和更新)本地状态。

How interesting.

很有意思。

Consider the following counter application:

考虑以下计数器应用程序:

With the Counter component shown below:

随着Counter组件如下所示:

Simple, huh?

简单吧?

Let me ask you one simple question. Why exactly do we have this component as a Class component?

我问一个简单的问题。 为什么我们确切地将此组件作为类组件?

Well, the answer is simply because we need to keep track of some local state within the component.

答案很简单,因为我们需要跟踪组件内的某些局部状态。

Now, here’s the same component refactored to a functional component with access to state via the useState hooks.

现在,这里是将相同的组件重构为可以通过useState钩子访问状态的功能组件。

What’s different?

有什么不同?

I’ll walk you through it step by step.

我将逐步指导您。

A functional component doesn’t have all the Class extend ... syntax.

一个功能组件并不具有所有的Class extend ...语法。

function CounterHooks() {  }

It also doesn’t require a render method.

它也不需要render方法。

function CounterHooks() {    return (      <div>        <h3 className="center">Welcome to the Counter of Life </h3>        <button           className="center-block"           onClick={this.handleClick}> {count} </button>      </div>    ); }

There are two concerns with the code above.

上面的代码有两个问题。

  1. You’re not supposed to use the this keyword in function components.

    您不应该在功能组件中使用this关键字。

  2. The count state variable hasn’t been defined.

    count状态变量尚未定义。

Extract handleClick to a separate function within the functional component:

提取handleClick到功能组件内的单独功能:

function CounterHooks() {  const handleClick = () => {      }  return (      <div>        <h3 className="center">Welcome to the Counter of Life </h3>        <button           className="center-block"           onClick={handleClick}> {count} </button>      </div>    ); }

Before the refactor, the count variable came from the class component’s state object.

在重构之前, count变量来自类组件的状态对象。

In functional components, and with hooks, that comes from invoking the useState function or hook.

在功能组件中,并带有挂钩,这是通过调用useState函数或挂钩来实现的。

useState is called with one argument, the initial state value e.g. useState(0) where 0 represents the initial state value to be kept track of.

用一个参数调用useState ,它是初始状态值,例如useState(0) ,其中0表示要跟踪的初始状态值。

Invoking this function returns an array with two values.

调用此函数将返回具有两个值的数组。

//? returns an array with 2 values. useState(0)

The first value being the current state value being tracked, and second, a function to update the state value.

第一个值是要跟踪的当前状态值,第二个是更新状态值的功能。

Think of this as some state and setState replica - however, they aren’t quite the same.

可以将其视为statesetState副本-但是它们并不完全相同。

With this new knowledge, here’s useState in action.

有了这些新知识,这里的useState作用。

function CounterHooks() {  // ?   const [count, setCount] = useState(0);  const handleClick = () => {    setCount(count + 1)  }  return (      <div>        <h3 className="center">Welcome to the Counter of Life </h3>        <button           className="center-block"           onClick={handleClick}> {count} </button>      </div>    ); }

There are a few things to note here, apart from the obvious simplicity of the code!

除了代码的明显简单性,这里还需要注意几件事!

One, since invoking useState returns an array of values, the values could be easily destructed into separate values as shown below:

一个,由于调用useState返回一个值数组,因此可以很容易地将这些值分解为单独的值,如下所示:

const [count, setCount] = useState(0);

Also, note how the handleClick function in the refactored code doesn’t need any reference to prevState or anything like that.

另外,请注意,重构代码中的handleClick函数如何不需要任何对prevState引用或类似的引用。

It just calls setCount with the new value count + 1.

它只是用新值count + 1调用setCount

const handleClick = () => {    setCount(count + 1) }

This is because of the correct value of the count state variable will always be kept across re-renders.

这是因为count状态变量的正确值将始终在重新渲染之间保留。

So, need to update count state variable, just call setCount with the new value e.g. setCount(count + 1)

因此,需要更新计数状态变量,只需使用新值调用setCount ,例如setCount(count + 1)

Simple as it sounds, you’ve built your very first component using hooks. I know it’s a contrived example, but that’s a good start!

听起来很简单,但是您已经使用钩子构建了第一个组件。 我知道这是一个人为的例子,但这是一个好的开始!

Nb: it’s also possible to pass a function to the state updater function. This is usually recommended as with class’ setState when a state update depends on a previous value of state e.g. setCount(prevCount => prevCount + 1)

Nb :也可以将一个函数传递给状态更新器函数。 当状态更新取决于状态的先前值时,通常建议与类的setState一起使用,例如setCount(prevCount => prevCount + 1)

多个useState调用 (Multiple useState calls)

With class components, we all got used to set state values in an object whether they contained a single property or more.

使用类组件,我们都习惯于在对象中设置状态值,无论它们包含单个属性还是更多属性。

// single property state = {  count: 0}// multiple properties state = { count: 0, time: '07:00'}

With useState you may have noticed a subtle difference.

使用useState您可能已经注意到了细微的差别。

In the example above, we only called useState with the actual initial value. Not an object to hold the value.

在上面的示例中,我们仅使用实际初始值调用useState 。 不是持有价值的对象。

useState(0)

So, what if we wanted to another state value?

那么,如果我们要另一个状态值呢?

Can multiple useState calls be used?

可以使用多个useState调用吗?

Consider the component below. Same as before but this time it tracks time of click.

考虑下面的组件。 与之前相同,但是这次它跟踪点击时间。

As you can see, the hooks usage is quite the same, except for having a new useState call.

如您所见,钩子用法是完全一样的,除了有一个新的useState调用。

const [time, setTime] = useState(new Date())

Now time is used in the rendered JSX to retrieve the hour, minute and second of the click.

现在,在渲染的JSX使用time来获取点击的小时,分​​钟和秒。

<p className="center">    at: { `${time.getHours()} : ${time.getMinutes()} : ${time.getSeconds()}`}</p>

Great!

大!

However, is it possible to use an object with useState as opposed to multiple useState calls?

但是,是否可以将对象与useState而不是多个useState调用一起使用?

Absolutely!

绝对!

If you choose to do this, you should note that unlike setState calls, the values passed into useState replaces the state value. setState merges object properties but useState replaces the entire value.

如果选择执行此操作,则应注意,与setState调用不同,传递给useState的值将替换状态值。 setState合并对象属性,但useState替换整个值。

效果钩 (The Effect Hook)

With class components you’ve likely performed side effects such as logging, fetching data or managing subscriptions.

使用类组件,您可能会产生副作用,例如日志记录,获取数据或管理订阅。

These side effects may be called “effects” for short, and the effect hook, useEffect was created for this purpose.

这些副作用可以简称为“效果”, useEffect创建了效果挂钩useEffect

How’s it used?

如何使用?

Well, the useEffect hook is called by passing it a function within which you can perform your side effects.

好吧,通过向useEffect挂钩传递了一个函数,您可以在其中执行副作用,从而调用它。

Here’s a quick example.

这是一个简单的例子。

useEffect(() => {  // ? you can perform side effects here  console.log("useEffect first timer here.")})

To useEffect I’ve passed an anonymous function with some side effect called within it.

为了使用useEffect我传递了一个匿名函数,该函数内部具有一些副作用。

The next logical question is, when is the useEffect function called?

下一个逻辑问题是,何时调用useEffect函数?

Well, remember that in class components you had lifecycle methods such as componentDidMount and componentDidUpdate.

好吧,请记住,在类组件中,您具有生命周期方法,例如componentDidMountcomponentDidUpdate

Since functional components don’t have these lifecycle methods, useEffect kinda takes their place.

由于功能组件没有这些生命周期方法,因此useEffect 有点替代了它们。

Thus, in the example above, the function within useEffect also known as the effect function, will be invoked when the functional component mounts (componentDidMount) and when the component updates componentDidUpdate).

因此,在上面的示例中,当安装功能组件( componentDidMount )以及组件更新componentDidUpdate时,将调用useEffect的函数(也称为效果函数)。

Here’s that in action.

这就是行动。

By adding the useEffect call above to the counter app, here’s the behavior we get.

通过将上面的useEffect调用添加到计数器应用中,这就是我们得到的行为。

NB: The useEffect hook isn’t entirely the same as componentDidMount + componentDidUpdate. It can be viewed as such, but the implementation differs with some subtle differences.

注意useEffect挂钩与componentDidMount + componentDidUpdate并不完全相同。 可以这样看,但是实现方式有所不同,但有一些细微的差异。

It’s interesting that the effect function was invoked every time there was an update. That’s great, but it’s not always the desired functionality.

有趣的是,每次更新时都会调用effect函数。 很好,但这并不总是所需的功能。

What if you only want to run the effect function only when the component mounts?

如果只想在组件安装时才运行效果功能怎么办?

That’s a common use case and useEffect takes a second parameter, an array of dependencies to handle this.

这是一个常见的用例, useEffect需要第二个参数,一个依赖项数组来处理这个问题。

If you pass in an empty array, the effect function is run only on mount — subsequent re-renders don’t trigger the effect function.

如果传入空数组,则效果功能仅在安装时运行-后续重新渲染不会触发效果功能。

useEffect(() => {    console.log("useEffect first timer here.")}, [])

If you pass any values into this array, then the effect function will be run on mount, and anytime the values passed are updated. i.e if any of the values are changed, the effected call will re-run.

如果将任何值传递到此数组,则效果功能将在安装时运行,并且在任何时候更新传递的值。 即,如果任何值更改,则受影响的呼叫将重新运行。

useEffect(() => {    console.log("useEffect first timer here.")}, [count])

The effect function will be run on mount, and whenever the count function changes.

效果功能将在安装时以及计数功能更改时运行。

What about subscriptions?

订阅呢?

It’s common to subscribe and unsubscribe from certain effects in certain apps.

在某些应用程序中订阅和取消订阅某些效果很常见。

Consider the following:

考虑以下:

useEffect(() => {  const clicked = () => console.log('window clicked');  window.addEventListener('click', clicked);}, [])

In the effect above, upon mounting, a click event listener is attached to the window.

在上面的效果中,安装后,单击事件侦听器将附加到窗口。

How do we unsubscribe from this listener when the component is unmounted?

卸载组件后,我们如何退订此侦听器?

Well, useEffect allows for this.

好吧, useEffect允许这样做。

If you return a function within your effect function, it will be invoked when the component unmounts. This is the perfect place to cancel subscriptions as shown below:

如果您在effect函数中返回一个函数,则在卸载组件时将调用该函数。 这是取消订阅的理想场所,如下所示:

useEffect(() => {    const clicked = () => console.log('window clicked');    window.addEventListener('click', clicked);    return () => {      window.removeEventListener('click', clicked)    } }, [])

There’s a lot more you can do with the useEffect hook such as making API calls.

您可以使用useEffect挂钩做更多的事情,例如进行API调用。

建立自己的挂钩 (Build Your own Hooks)

From the start of this article we’ve taken (and used) candies from the candy box React provides.

从本文开始,我们从React提供的糖果盒中提取(并使用了)糖果。

However, React also provides a way for you to make your own unique candies — called custom hooks.

但是,React还为您提供了一种制作自己独特的糖果的方法-称为自定义钩子。

So, how does that work?

那么,如何运作?

A custom hook is just a regular function. However, its name must begin with the word, use and if needed, it may call any of the React hooks within itself.

自定义钩子只是一个常规函数。 但是,其名称必须以单词use开头,如果需要,它可以调用其内部的任何React钩子。

Below’s an example:

下面是一个示例:

钩子规则 (The Rules of Hooks)

There are two rules to adhere to while using hooks.

使用挂钩时要遵守两个规则。

  1. Only Call Hooks at the Top Level i.e. not within conditionals, loops or nested functions.

    仅在顶层(不在条件,循环或嵌套函数中)的呼叫挂钩。

  2. Only Call Hooks from React Functions i.e. Functional Components and Custom Hooks.

    仅来自React函数的呼叫挂钩,即功能组件和自定义挂钩。

This ESLint plugin is great to ensure you adhere to these rules within your projects.

这个ESLint 插件非常适合确保您在项目中遵守这些规则。

其他糖果 (Other Candies)

We have considered a few of the hooks React provides, but there’s more!

我们已经考虑了React提供的一些钩子,但是还有更多!

This introduction should have prepared you to take on the perhaps more dense documentation. Also checkout my live editable react hooks cheatsheet.

本简介应该已经为您准备好准备也许更密集的文档 。 还要检查我的实时可编辑react hooks速查表

翻译自: https://www.freecodecamp.org/news/learn-the-basics-of-react-hooks-in-10-minutes-b2898287fe5d/

react hooks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值