在React中将鼠标悬停

时间:2018-12-31 06:23:47

标签: javascript reactjs jsx

我试图在鼠标悬停在另一个div元素上时显示div。我已经通过onMouseEnter和onMouseLeave做到了这一点。

这里的问题是,如果您快速从一个div移到另一个div(这是一个包含产品数据的div数组),则index [0]的值将变为true。

它的工作方式是当鼠标进入其中一个数组时,我将其初始化为false,该数组变为true,并显示所需的div。离开后,将其设置回false。

this.state = {
        isProductsHovering: new Array(this.props.currentProducts.length).fill(false)
    };

handleMouseHover = (idx) => {
    this.setState({
        isProductsHovering: update(this.state.isProductsHovering, {
            [idx]: { $set: !this.state.isProductsHovering[idx] }
        })
    })
}

render() {
    return this.props.currentProducts.map((product, idx) => {
        return <Fragment key={idx}>
            <div className="product-grid-view col-6 col-md-4" >
                <div
                    className=" product-holder"
                    onMouseEnter={this.handleMouseHover.bind(this, idx)}
                    onMouseLeave={this.handleMouseHover.bind(this, idx)}>
                    <div className="image-container" align="center">
                        <img src={"/img/product-3.jpg"} alt="" />
                        {
                            this.state.isProductsHovering[idx] &&
                            <div className="product-buttons">
                                <Link to={`products/${product.id}`} className="btn-detail" text="View Details" />
                                <Link to='#' className="btn-cart" icons={["icon-cart", "icon-plus"]} />
                            </div>
                        }
                    </div>
                    <div className="details-holder">
                        <span className="part-text">{product.desc}</span><br />
                        <span className="manufacturer-text">{product.manufacturer.name}</span>
                        <div className="product-review_slide">
                            <Stars values={product.averageRating} {...starsRating} />
                            <span className="product-review">{getLength(product.reviews)} review</span>
                        </div>
                        <span className="product-price">{product.salesPrice.toFixed(2)}</span>
                        <span className="product-currency">SR</span>
                    </div>
                </div>
            </div>
        </Fragment>
    })
}

更新

我做了一个stackblitz项目,以重现与建议相同的问题:

https://stackblitz.com/edit/react-mouse-hover

对于每个想要明白我的意思的人。我已附上问题的照片。如果将鼠标移到两个div上(尽可能快地上下移动),则会发生这种情况:

mouse hover broken

3 个答案:

答案 0 :(得分:2)

对于这种情况,我不会依靠数组和索引来使其工作。您会使handleMouseHover函数和isHovering的检查更加复杂。

处理这种情况的一种“更多反应”方法就是简单地使每个产品本身成为一个组件。并且此Product组件将具有自己的isHoveredhandleOnHover方法状态,这样您就可以创建更简洁和可靠的代码,而不必完全依赖数组index

App.js 可以很简单:

class App extends Component {

  render() {
    return (
      <div>
      {
        data.map(product =>
          <Product product={product} />
        )
      }
      </div>
    )
  }
}

新的 Product.js

import React from 'react'
import ReactHoverObserver from 'react-hover-observer';

export default class Product extends React.Component {
  render() {
    const { product } = this.props
    return (
      <ReactHoverObserver className="product-grid-view col-6 col-md-4">
      {
        ({isHovering}) => (
          <div className=" product-holder">
            <div className="image-container" align="center">
              <img src={"/img/product-3.jpg"} alt="" />
              {
                isHovering &&
                <div className="product-buttons">
                  <button className="btn-detail">View Details</button>
                </div>
              }
            </div>
            <div className="details-holder">
              <span className="part-text">{product.desc}</span><br />
              <span className="manufacturer-text">{product.manufacturer.name}</span>
              <div className="product-review_slide">
                <span className="product-review">0 review</span>
              </div>
              <span className="product-price">{product.salesPrice.toFixed(2)}</span>
              <span className="product-currency">Currency</span>
            </div>
          </div>
        )
      }
      </ReactHoverObserver>
    )
  }
}

我已将管理人员放在Stackblitz中:https://stackblitz.com/edit/react-mouse-hover-2cad4n

答案 1 :(得分:1)

Liren的答案是一个很好的建议,将有助于简化代码。我还注意到的一件事是,HoverObserver有时不会“听到”事件,并且由于悬停进入和悬停退出事件正在侦听同一事件,因此按钮的显示状态将变为相反的状态(即,它将在鼠标没有悬停时显示;在鼠标悬停在观察者上方时隐藏)。

我建议您摆脱ReactHoverObserver HOC,而只是监听onMouseOver进行悬浮输入,以及onMouseLeave进行悬浮退出。这样,即使div没有注册悬停进入或退出,它也将很容易重置,因为onMouseOver会将显示状态切换为true,而onMouseLeave会将按钮的显示状态可靠地设置为false。

在此处查看文档中的这些事件: https://reactjs.org/docs/events.html#mouse-events

答案 2 :(得分:0)

(从数组或组件中)触发它的方式是语义,真正的问题是这些事件并不总是触发。

我遇到了同样的问题,显然反应的事件不是那么可靠。 就我而言,我可能生活在一个工具提示没有关闭的情况下,但是没有生活在两个工具提示都打开的情况下。为了解决我的问题,我恢复了旧的dom操作-每次出现工具提示时,都会使其他所有工具提示不可见。

它看起来像这样:

showTooltip() {

    // Clear old tooltips, EventTooltip is the name of my tooltip class.
    Array.from(document.getElementsByClassName('EventTooltip'))
        .forEach(tooltip=>tooltip.style = 'display:none;')

    this.setState({showTooltip: true})
}

hideTooltip() {
    this.setState({showTooltip: false})
}