react hooks使用_如何使用React和Hooks检测外部点击

本文介绍了如何在React中使用Hooks检测外部点击事件。通过创建一个通用且可重用的组件,结合 useEffect 钩子来实现点击事件监听和解除监听。文章详细解释了组件结构、生命周期方法的替换以及如何处理复杂子节点的情况。
摘要由CSDN通过智能技术生成

react hooks使用

by Andrei Cacio

通过安德烈·卡西奥(Andrei Cacio)

如何使用React和Hooks检测外部点击 (How to detect an outside click with React and Hooks)

“外部点击”是什么意思? (What does “Outside Click” mean?)

You can think of it as the “anti-button”. An outside click is a way to know if the user clicks everything BUT a specific component. You may have seen this behavior when opening a dropdown menu or a dropdown list and clicking outside of it to close it.

您可以将其视为“反按钮”。 外部点击是一种了解用户是否单击所有按钮但又单击特定组件的方法。 打开下拉菜单或下拉列表并在其外部单击以将其关闭时,您可能已经看到此行为。

There are all sorts of other use cases for such a feature:

此类功能还有其他各种用例:

  • when closing dropdown lists

    关闭下拉列表时
  • when closing modal windows

    关闭模式窗口时
  • when transitioning in and out of edit mode for editable elements

    在可编辑元素的进出编辑模式转换时
  • closing

    闭幕
  • and many more…

    还有很多…

Now let’s see how we can a write a generic and reusable React component which will incorporate this behavior.

现在让我们看看如何编写一个通用且可重用的React组件,它将结合这种行为。

看起来如何 (How it will look like)

A happy flow should look like this:

一个快乐的流程应如下所示:

组件结构 (Component structure)

For this component to work we will need to attach a click event handler on the document itself. This will help us detect when we are clicking anywhere on the page. Then we will need to check if our clicked target differs from our wrapped element. So a basic structure will look like this:

为了使该组件正常工作,我们需要在文档本身上附加一个click事件处理程序。 这将帮助我们检测何时单击页面上的任意位置。 然后,我们将需要检查单击的目标是否与包装的元素不同。 因此,基本结构如下所示:

For the first example, we will start coding using the React Class style and then refactor it with the new Hooks API.

对于第一个示例,我们将开始使用React Class样式进行编码,然后使用新的Hooks API对其进行重构。

We implemented two lifecycle functions:

我们实现了两个生命周期功能:

  • componentDidMount(): will attach the event listener

    componentDidMount() :将附加事件监听器

  • componentWillUnmount(): will clean up the click handler before the component will get destroyed

    componentWillUnmount() :将在组件销毁之前清理单击处理程序

and then we render whatever that components wrap over. For our first example above it will render the <span>.

然后我们渲染组件包裹的所有内容。 对于上面的第一个示例,它将呈现<span>。

“ ClickOutside”条件 (The “ClickOutside” condition)

Now we need to check if the user clicks outside of the wrapped child. One naive solution is to compare the target element (the element that we click) with our child’s node. But, this will work only if we have a simple (single level) node as a child. If our wrapped child has more sub-nodes, then this solution will fail.

现在,我们需要检查用户是否在被包装的孩子之外单击。 一种幼稚的解决方案是将目标元素(我们单击的元素)与孩子的节点进行比较。 但是,只有当我们有一个简单的(单级)节点作为子节点时,这才起作用。 如果我们的包装子节点具有更多子节点,则此解决方案将失败。

Luckily there is a method called .contains() which tells us if a node is a child of a given node. The next step will be to gain access to our child’s node. To achieve this we will use React Refs.

幸运的是,有一个方法称为.contains() ,它告诉我们一个节点是否是给定节点的子级。 下一步将是访问我们孩子的节点。 为此,我们将使用React Refs

Refs are React’s way of giving us access to the raw node object. We will also use Reacts API for handling the this.props.children components. We need this API because we will inject our created ref to our wrapped child. Having this in mind our component will look like so:

引用是React使我们能够访问原始节点对象的方式。 我们还将使用Reacts API来处理this.props.children组件。 我们需要此API,因为我们会将创建的ref注入包装的孩子。 考虑到这一点,我们的组件将如下所示:

Perfect, this should work as expected. At least for our happy flow (one wrapped child). If we intend to wrap more than one node, we need to make some adjustments:

完美,这应该可以正常工作。 至少为了我们的幸福(一个被包裹的孩子)。 如果打算包装多个节点,则需要进行一些调整:

  • we need to have an array of refs (as many as our wrapped children)

    我们需要一个ref数组(与包裹的孩子一样多)
  • we need to use React.Children.map to clone each child and inject the associated ref from our private array of refs

    我们需要使用React.Children.map来克隆每个子对象,并从我们的ref私有数组中注入关联的ref

This should do just fine. Now let’s refactor this using Hooks!

这应该很好。 现在,让我们使用Hooks重构它!

钩子 (Hooks)

React 16.8 introduced a new API called Hooks. With Hooks we can write less code and get a smaller footprint on our codebase. Also, Hooks take advantage of functions which are first class citizens in JavaScript. If you are familiar with stateless functional components in React you are halfway there. Our initial refactor will look like so:

React 16.8引入了一个称为Hooks的新API。 使用Hooks,我们可以编写更少的代码,并在我们的代码库中占用更小的空间。 另外,Hooks利用了JavaScript中的一等公民功能。 如果您熟悉React中的无状态功能组件 ,那么您已经半途而废了。 我们的初始重构如下所示:

Up until now, we are still using the “old” React API to declare a simple stateless functional component. However, we still need those lifecycle functions to attach our handler on the document node.

到目前为止,我们仍在使用“旧的” React API来声明一个简单的无状态功能组件。 但是,我们仍然需要那些生命周期函数来将处理程序附加到文档节点上。

Here is where Effect hook comes in. The Effect hook will replace our “componentDidMount” and “componentWillUnmount” methods. The Effect Hook will be called right after the components renders so it will help us attach our desired handler on time. Also for the cleanup part, if the Effect hook returns a function that function will be called right before the component will be unmounted. So it is just the right time to do some cleanup. In the next refactor, things will become a bit clearer.

这是效果钩的地方 效果钩子将取代我们的“ componentDidMount ”和“ componentWillUnmount ”方法。 在组件渲染之后,将立即调用效果挂钩,这样将有助于我们按时附加所需的处理程序。 同样对于清理部分,如果Effect挂钩返回一个函数,则该函数将在卸载组件之前立即被调用。 因此,这是进行清理的正确时机。 在下一个重构中,情况将变得更加清晰。

This is the final form of our functional component using the Effect Hook. If you want to see both examples in action you can run them below. (You can default export either the Class component or the functional component and the app will behave the same.)

这是使用效果挂钩的功能组件的最终形式。 如果您想同时看到两个示例,可以在下面运行它们。 ( 您可以默认导出Class组件或功能组件,并且应用程序的行为相同。 )

结论 (Conclusion)

Even though the click outside behavior is a widely used feature, it may not be so straightforward to implement in React. With this example, I took the liberty to experiment a bit with React Hooks and build the solution in two ways to compare the two approaches. I am a big fan of functional components, and now with the help of Hooks, we can take them to the next level.

即使外部点击行为是广泛使用的功能,在React中实现起来也可能不是那么简单。 在这个示例中,我可以自由地对React Hooks进行一些实验,并以两种方式构建解决方案以比较这两种方法。 我是功能组件的忠实拥护者,现在在Hooks的帮助下,我们可以将它们提升到一个新的水平。

翻译自: https://www.freecodecamp.org/news/how-to-detect-an-outside-click-with-react-and-hooks-25dbaa30abcd/

react hooks使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值