188体育怎么提现

通过鲁本小马丁内斯。

到目前为止,见多眼广的读者们,肯定已经浏览、浏览或至少收藏了六篇有关React 16.8最受期待的功能:钩子的文章。你可能已经读过或听说过它们有多好,有多糟糕,甚至可能有多困惑。你可能会问自己“我为什么要了解这一点?”你可能希望得到一个更好的答案"因为这是新事物".如果你遵循了一些钩子指南,你可能会发现自己在问“但为什么?我可以使用类做同样的事情!”

信贷@lizandmollie.

如果这听起来很熟悉,那可能是因为它是我们每次所面临的每次都要学习新事物的同一个周期。学习新事物对于任何人来说都是困难的,并且重新学习你已经知道的东西可能是特别令人沮丧的。您本能的反应可能是在您已经知道的内容中框架新事物。当我第一次分享关于钩子的钩子的学习到Okcupid时,我制作了一个图表映射组件生命周期方法来挂钩替代方案,让我看起来有188bet金宝搏官网点像这个家伙:

作者的注意事项:向Okcupid Web团队道歉,以成为我的豚鼠188bet金宝搏官网

事实证明,这是一种非常令人困惑的学习钩子的方法!许多概念不能很好地映射,或者在一种方法与另一种方法之间看起来不必要地更加复杂。我不再继续谈论我的失败,而是开始谈论好的东西。这并不是一个全面的关于钩子的指南,但是我希望当您读完之后,您会有足够的兴趣来编写第一个使用钩子的组件。根据我的经验,这才是真正的秘密:在你开始为自己写之前,它不一定会点击。闲话少说,这是人类已知的学习钩子的最佳方法。

我是说没关系
这是我个人在出版时间发现的

累了:设置状态

连线:useState

我们从最基本的开始。您可能已经看到了对这个钩子的解释,如果是这样,请跳到下一节,在那里我们将开始进行更深入的讨论。

我们学到反应中的第一件事之一是制作一个有状态的组成部分。你,像我一样,学会通过扩展来编写一个组件反应。组件(或者更可能是使用React.createClass,但我们不谈论那些黑暗的日子)。你学会了使用this.setState({某些键:Somevalue})要修改组件的状态,请记住传递的键/值对设置状态用新值覆盖旧状态,其他所有内容就会合并进来。哦,不要忘记初始化状态对象这样当我们尝试时就不会出错设置状态.当然,别忘了.bind每个都在构造函数中修改状态的函数,或记得使用箭头函数语法在您的团队中的某人几年前安装了Babel插件。

让我们暂时忘掉这一切。让我们概述一下构建一个简单的、有状态的点击计数器组件所需要的东西:

  1. 我们需要知道当前的点击键(让我们打电话给这个CurrentCount.
  2. 我们需要一种方法来增加点击计数(让我们称之为setCurrentCount

如果我们想象一下,我们有这些先决条件,我们可以这样写:

从“React”中导入React;

const Counter = () => {
回报(

当前计数:{currentCount}

通常情况下我们可能会去设置状态要将其变为现实,就意味着必须将这个微小的功能组件重构为成熟的类组件。但等一下——这就是我们的第一个陷阱。

import React, {useState} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);

回报(

当前计数:{currentCount}

“嗯,刚刚发生了什么?!”你可能会问自己。寒冷,自我。这是一个钩子!钩子允许功能组件钩进以前只对类组件可用的特性,如状态。

useestate.Hook是一个接受单个参数的函数:初始状态(在本例中为0),并按顺序返回一个数组中的值和该状态值的setter。当您调用setter时,React会用更新后的状态值重新呈现组件,就像您调用时一样设置状态

“为什么阵列破坏?”你问?嗯,这样你就可以命名值和Setter,无论你想要的何种何种。当然,你可以使用useestate.挂钩尽可能多的时间,因为您可以在组件中携带多次,因此如果需要,可以跟踪多条状态,而无需将状态表示转换为对象。我们将更多地了解到在下一节中为我们提供了影响的机会。

累:单个对象保持状态

有线:​​单独的疑虑状态。

一个整洁的事情之一useestate.你的组件的状态表示不是吗要成为一个对象 - 它可以是一个数字,字符串,或者真的是您想要的(包括对象)。但这是添加新状态属性的意思是什么?让我们说你后来决定需要跟踪另一个有状态财产。当状态是一个对象时,这与添加另一个密钥一样简单。现在,它像添加另一个电话一样简单useestate.

import React, {useState} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const [isclick, setisclick] = useState(false);

回报(

当前计数:{currentCount}
点击:{isclicking}
<按钮
onclick = {()=> setCurrentCount(CurrentCount + 1)}
onMouseDown = {() = > setIsClicking (true)}
onMouseUp {() = > setIsClicking (false)} >
增量
< / >按钮
< / div >
);
};

这也使我们能够灵活地将相关的代码块分组在一起,而不是将可能不相关的状态更改分组在一起设置状态调用。例如,如果我想将一些事件处理程序移出返回块,我可以用最合适的代码进行分组,如下所示:

import React, {useState} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const incrementCounter = () => setCurrentCount(currentCount + 1);

const [isclick, setisclick] = useState(false);
const onMouseDown = () => setisclick (true);
const onMouseUp = () => setisclick (false)

回报(

当前计数:{currentCount}
点击:{isclicking}
<按钮
onClick = {incrementCounter}
onMouseDown = {onMouseDown}
onMouseUp {onMouseUp} >
增量
< / >按钮
< / div >
);
};

很酷,对吧?在传统的类组件中,这些状态属性必须一起存在于单个对象中,并且状态的初始化和修改状态的函数可能会分散在整个组件中,而不是用相关的逻辑分组在一起。对于这么简单的组件,好处可能不大,但对于较大的组件,它确实会对组件的可读性产生影响。

累了:生命周期方法

有线:​​当您需要更改时更改的数据

我们学到的useestate.可以取代(并在某些方面有所改进)设置状态.但是,我们能用类组件中的生命周期方法做的所有其他强大的事情呢?对于经验丰富的React开发人员来说,下面的内容可能会让他们感到不安。

生命周期方法是一种抽象,它让我们思考我们所处的组件呈现阶段。名字像componentDidMountcomponentDidUpdate,componentwillunmount.对我们那些已经使用它们多年来一直使用它们并且可靠地了解他们的何时以及为什么他们会跑的东西,这些东西可以非常令人困惑地学习。那就是在我的经验中,我发现我们通常以一些可预测的模式使用它们。如果这些声音熟悉,请举手:

  1. componentDidMountcomponentwillunmount.用于附加/删除事件侦听器,或设置/清除超时。(例如:侦听文档滚动或按键事件以更改状态)
  2. componentDidMountcomponentDidUpdate用于加载基于道具/状态变化的东西。(例如:当我们进入页面时加载数据,当状态改变时重新加载)
  3. componentDidMountcomponentDidUpdate用于根据PROP / State Change重新计算某些DOM属性。(示例:在状态更改后滚动到元素的顶部)

通常,我们同时使用几个这样的模式,哦,这些生命周期方法会变得很混乱吗?相关的逻辑必然会在这些方法中蔓延开来,并且很难理解在混乱中发生了什么。但事情并不一定是这样的!从根本上说,这些模式中的大多数都可以简化为:当事情发生时做一些事情。幸运的是,我们有一些钩子可以帮助解决这个问题。

假设我们想要删除计数器组件中的按钮,而只是侦听文档上的单击。与其编写生命周期方法来设置和拆除这些事件处理程序,不如使用一个名为useEffect

import React, {useState, useEffect} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const incrementCounter = () => setCurrentCount(currentCount + 1);
useEffect (() = > {
文档。addEventListener(“点击”,incrementCounter);

Return () => {
文档。removeEventListener(“点击”,incrementCounter);
};
}, [incrementCounter]);

const [isclick, setisclick] = useState(false);
const onMouseDown = () => setisclick (true);
const onMouseUp = () => setisclick (false);
useEffect (() = > {
文档。addEventListener(“mousedown”,onMouseDown);
document.addeventListener(“mouseUp”,OnmouseUp);

Return () => {
文档。removeEventListener(“mousedown”,onMouseDown);
文档。removeEventListener(“mouseup”,onMouseUp);
};
},[onmousedown,onmouseup]);

回报(

当前计数:{currentCount}
点击:{isclicking}
< / div >
);
};

哇,那是很多。让我们专注于其中一个新的useEffect块。

useEffect (() = > {
文档。addEventListener(“点击”,incrementCounter);

Return () => {
文档。removeEventListener(“点击”,incrementCounter);
};
});

这个整洁的小钩子可能很难理解——使用好的老式命名函数可能更容易理解(我想念那些):

useEffect(功能设置(){
文档。addEventListener(“点击”,incrementCounter);

返回函数tearDown() {
文档。removeEventListener(“点击”,incrementCounter);
};
});

这更好了。基本上,我们告诉这些组件运行我们的设置()函数在其呈现后进行清理,并使用拆卸函数,在下一次渲染之前。例如,如果这个组件被渲染三次,它将运行如下函数:

  1. 渲染
  2. 设置()
  3. 渲染(x2)
  4. 拆除()
  5. 设置()
  6. 渲染(x3)
  7. 拆除()
  8. 设置()

…等等。但是,为了效率,我们可以选择不通过useEffect第二个参数:

useEffect(功能设置(){
文档。addEventListener(“点击”,incrementCounter);

返回函数tearDown() {
文档。removeEventListener(“点击”,incrementCounter);
};
}, [incrementCounter]);

第二个参数是应该导致组件重新运行的项列表设置拆卸功能。通常,这个列表将包括您在useEffect电话本例中,incrementCounter.这让我们避免了浪费的设置和拆卸。更强大的是,它可以帮助我们防止该效果运行不止一次,只需向它传递一个空值列表,其中包含要更改的值。有用的!

在上面的例子中,我们useEffect每次设置一些文档事件侦听器incrementCounter更改,但我们可以使用同样的钩子来运行任何类型的副作用,我们希望从订阅和取消订阅到Web套接字,在某些道具更改时击中更新数据的API,或者我们的任何其他Prop或状态驱动操作可能需要采取。

在这一点上值得注意的是拆卸返回值是完全可选的。我们并不总是有一些我们想要清理的东西,但有时我们愿意,我们可以将这种相关的逻辑保持在一起。在我们的副作用之后,它也可以有用的提醒清理,我们之前可能忘记了清理componentwillunmount.

累了:组件的方法

连线:useCallback

“但是等等!”,你现在可能会说,我们在渲染函数中定义了incrementCounter !每次渲染都会重新定义,所以我们的钩子不会每次都运行吗?”好吧,好吧,我没有意识到您如此关注这个过度扩展的示例组件。但你完全正确!

import React, {useState, useEffect} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const incrementCounter = () => setCurrentCount(currentCount + 1);

useEffect (() = > {
文档。addEventListener(“点击”,incrementCounter);

Return () => {
文档。removeEventListener(“点击”,incrementCounter);
};
}, [incrementCounter]);

回报(

当前计数:{currentCount}
< / div >
);
};

因为incrementCounter是被重新定义在每个渲染,使用它的第二个参数useEffect并没有给我们带来什么好处。谢天谢地,这里有个挂钩!

import React, {useState, useEffect, useCallback} from " React ";

const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const incrementCounter = useCallback(
() => setCurrentCount(currentCount + 1),
[setCurrentCount, currentCount],
);

useEffect (() = > {
文档。addEventListener(“点击”,incrementCounter);

Return () => {
文档。removeEventListener(“点击”,incrementCounter);
};
}, [incrementCounter]);

回报(

当前计数:{currentCount}
< / div >
);
};

这是我最喜欢的,也是最有用的钩子之一,即使你放弃了钩子的整个概念,你也会想把它放在你的工具带里。你给useCallback一个函数作为它的第一个参数,它返回它的一个记忆版本,它只在第二个参数中的任何项发生变化时重新计算。

这是特别有用的,因为我们都知道向下传递箭头函数作为道具没有好,因为这可能导致浪费的纠正者。现在,修复它在包装箭头函数时可以简单useCallback钩!这是一种简单的方法,可以挤出一些改进的性能,并防止不必要的重新呈现。

累了:重新选择

连线:useMemo

如果我没有谈论一个紧密的堂兄,我会在这一点上留下来useCallback,非常有用useMemo钩。当你发现自己在渲染块中计算一些昂贵的东西时,可以使用这个钩子。例如,如果你的组件体看起来像这样:

从“React”中导入React;

const MyComponent = ({someObject}) => {
const someNumber = Object.keys(someObject)
. map((关键)= > someObject(值))
.filter((value)=>值%2 === 0)
.reduce((sum, current) => sum + current, 0)
Const array =[…]新数组(someNumber)];

回报(

{array.map(() => )}
< / div >
);
};

(当然,这是一个荒谬的虚构的例子,但如果你一本正经地告诉我,你的代码库中没有这样的东西,我就把我的帽子吃了。)你可以把这个昂贵的计算包进去useMemo像这样:

import React, {useMemo} from " React ";

const MyComponent = ({someObject}) => {
const array = useMemo(() => {
const someNumber = Object.keys(someObject)
. map((关键)= > someObject(值))
.filter((value)=>值%2 === 0)
.reduce((sum, current) => sum + current, 0)
返回[…新数组(someNumber)];
}, [someObject]);

回报(

{array.map(() => )}
< / div >
);
};

现在,这个数组会只有如果值的价值,请重新计算someObject的变化。这比每次渲染都重新计算要高效得多(尽管仍然被承认比完全删除要低效得多,因为它非常糟糕™️)。在过去,图书馆喜欢重新选择给我们的工具以获得类似的性能优势,但现在您可以在不必导入其他库的情况下获得这些增益。

累:高阶组件/混合

连线:自定义钩子

一件事。回到我们的Counter示例(您认为我应该让Counter组件摆脱钩子——永远不!),如果我们出于一些难以理解的原因,想要在第二个组件中将单击处理程序附加到文档中,该怎么办?也许是一个点击就会产生随机数的。

import React, {useState, useEffect, useCallback} from " React ";

constrameNunbergenerator =()=> {
const [randomnumber,setrandomnumber] = usestate();
const getRandomNumber = useCallback(
()=> setrandomnumber(4),//保证随机
(setRandomNumber),
);

useEffect (() = > {
文档。addEventListener(“点击”,getRandomNumber);

Return () => {
文档。removeEventListener(“点击”,getRandomNumber);
};
}, [getRandomNumber]);

回报(

随机数为:{randomNumber}
< / div >
);
};

好吧,我们可以在新组件中重新定义逻辑,但这并不有趣。如果我们觉得聪明的话,我们可以使用更高阶的组件,或者渲染道具来做这件事。但这正是定制钩子真正发挥作用的地方。我们可以将共享逻辑抽象到一个可以调用的自定义钩子useDocumentClick

import React, {useState, useEffect, useCallback} from " React ";

函数useDocumentClick (onDocumentClick) {
useEffect (() = > {
文档。addEventListener(“点击”,onDocumentClick);

Return () => {
文档。removeEventListener(“点击”,onDocumentClick);
};
},[ondocumentClick]);


const Counter = () => {
const [currentCount, setCurrentCount] = useState(0);
const incrementCounter = useCallback(
() => setCurrentCount(currentCount + 1),
[setCurrentCount, currentCount],
);
useDocumentClick (incrementCounter);

回报(

当前计数:{currentCount}
< / div >
);
};

constrameNunbergenerator =()=> {
const [randomnumber,setrandomnumber] = usestate();
const getRandomNumber = useCallback(
()=> setrandomnumber(4),//保证随机
(setRandomNumber),
);
二手Contick(Getrandomnumber);

回报(

随机数为:{randomNumber}
< / div >
);
};

自定义钩子可以像使用其他钩子一样使用。自定义钩子的名字应该总是以使用,但除此之外,您可以在其中自由地做任何您想做的事情—包括使用其他钩子,如useestate.useEffect.组件永远不需要知道钩子的实现细节——只需要知道它的API。这可以帮助将复杂状态或副作用逻辑移出组件,并使该逻辑易于重用。您不一定希望对所有钩子都这样做,但这是在需要时使组件逻辑可重用的一种更简单的方法。

例如,如果您发现自己经常从组件进行API调用,您可以编写一个名为Useapi.

功能USEAPI(方法,端点,数据){
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [response, setResponse] = useState(null);

使用效果(async () => {)
尝试{
setIsLoading(真正的);
setResponse(null);
setError(空);

Const res = await fetch(端点,{方法,数据});

setisloading(false);
setResponse (res);
}捕捉(err) {
setisloading(false);
setError(错);

},[方法,端点,数据]);

返回{
回复,
错误,
insloading,
};

这样,你就有了一个与组件API通信的一致层。如果您正在使用像GraphQL和Apollo这样的现代技术,就像我们在OkCupid上开始使用的那样,已经有一些了188bet金宝搏官网伟大的开源项目为您提供一些这些强大的自定义钩子,以及越来越多的集合其他配套工具挂钩

一个警告⚠️

在使用钩子时,你必须记住一个主要规则:你的钩子必须每次组件呈现时,都以相同的顺序声明。这意味着:钩子不能在条件语句内部、条件返回后或循环中定义。钩子必须总是在缩进的“顶层”被调用。如果这看起来很奇怪,那是因为按照Javascript的标准,这是一个不寻常的限制。这是语言之上的额外约束,但对于React能够以正确的方式保存状态来说是必要的。关于为什么存在这个限制的更多信息,我建议您阅读丹·阿布拉莫夫的博客“反应过度”.好消息是:有一个eslint.插件来帮助你避免犯错。

你迷上了吗?

React钩子确实可以改变我们对组件中的状态和状态更新的思考方式,这可能会带来一些非常好的重构机会。虽然将我们的组件1:1地从类“转换”到钩子是很诱人的,但这通常会限制钩子所能提供的好处。我希望本指南能帮助您对钩子的强大功能产生兴趣,并帮助我们重新思考组件中的一些常见模式。优化现有代码的机会useCallbackuseMemo不能夸大,因为它们可以在我们现有的功能组件中提供一些简单的性能优势。关于什么时候使用钩子比使用类组件更直观的争论肯定会很激烈,但我认为至少钩子为我们提供了一些非常强大的新工具,用于表达有状态组件,甚至优化无状态组件。

最初发表在https://tech.188bet金宝搏官网okcupid.com.2019年2月27日。

188bet金宝搏官网OkCupid科技博客

阅读来自工程团队的故事,这些故事每天连接着数百万人

188bet金宝搏官网OkCupid科技博客

阅读来自工程团队的故事,这些故事每天连接着数百万人

188bet金宝搏官网OkCupid科技博客

阅读来自工程团队的故事,这些故事每天连接着数百万人

媒介是一个开放的平台,17亿读者来寻找洞察力和动态的思维。在这里,专家和未被发现的声音相似地潜入任何主题的核心,并将新的想法带到表面上。了解更多

遵循对您有关的作家,出版物和主题,您将在您的主页和收件箱中看到它们。探索

如果你有故事要讲,有知识要分享,有观点要分享,欢迎回家。在任何话题上发表你的想法都是简单而免费的。开始博客

获取Medium应用程序

一个“在App Store下载”的按钮,如果点击它,你就会进入iOS App Store
一个“打开,谷歌播放”的按钮,如果你点击它,就会进入谷歌播放商店