【问题标题】:React component behaves differently in Firefox and ChromeReact 组件在 Firefox 和 Chrome 中的行为不同
【发布时间】:2021-06-24 19:02:57
【问题描述】:

我编写了一个 React 组件 Tooltipable,它能够包装另一个组件并为其显示工具提示。

它在 Firefox 中运行良好。但是,在 Chrome 中 - 有时 - 当元素悬停在上面时,工具提示显示并不一致。

有人可以解释这种行为并建议如何纠正它吗?我相信它与 React 并没有真正的关系,只是我解决问题的方式和/或这两个浏览器呈现内容的方式。

这是一个 CodePen:

https://codepen.io/barciewicz/pen/MWpNJoy?editors=1000

【问题讨论】:

  • 简单的改进是在您的mouseEvent 处理程序周围添加一个if 语句-如果已经可见,请不要再次将该组件重新设置为可见...但是存在逻辑问题。一次只显示一个工具提示组件 - 那么为什么必须为每个列表项返回一个呢?如果您专注于显示/隐藏/更新单个组件而不是所有组件,您会发现性能升级 - 目前每次发生更改时,每个工具提示组件也必须更改
  • @MikeAbeln 看起来可能是这样,但实际上,React 会为您处理所有优化。当您将状态设置为相同的值时,React 会丢弃该值并保留旧值。一次只有一个工具提示(当实例返回 null 时,它不会被渲染),无论如何,它们都是同一个组件的所有实例。 React 的全部目的是将您的应用程序拆分为尽可能多的小组件,并尽可能缩小您的状态范围。如果你尊重 React 的基本规则,你会没事的。
  • @ErnestoStifano 很好的解释,谢谢!我忽略了 Tooltip 组件底部的三元语句。您下面的第 4 点很好地解释了故障。

标签: javascript reactjs google-chrome firefox


【解决方案1】:

这是一个工作示例。

我做了以下事情:

  1. mouseover 替换为mousemove
  2. mouseout 替换为mouseleave
  3. 固定列表标记(li 应该是 ul 的直接子代。您可以避免使用带有 Flexbox 或其他技术的列表,它应该仍然有效)。
  4. 我只是在光标和工具提示之间添加了一些空间(我添加了 5px,但 1px 也应该可以解决问题)。如果您不这样做,则每次出现工具提示时都会在文本元素上触发 mouseleave 事件(创建您注意到的故障效果)。

const Tooltip = ({x, y, content, visible}) => {
    const style = {
        position: 'fixed',
        left: x + 'px',
        top: y + 'px',
        background: 'black',
        color: 'white',
        padding: '.5%'
    };
    const tooltip = <span style={style}>{content}</span>;
    return visible ? tooltip : null;
};

const Tooltipable = ({component, tooltipContent}) => {
    const [tooltipXy, setTooltipXy] = React.useState({x: 0, y: 0});
    const [tooltipVisible, setTooltipVisible] = React.useState(false);

    const handleMouseOver = (e) => {
        setTooltipXy({x: e.clientX + 5, y: e.clientY + 5});
        setTooltipVisible(true);
    };

    const handleMouseOut = () => {
        setTooltipVisible(false);
    };

    return (
        <li>
            <span
                style={{background: 'pink'}}
                onMouseLeave={handleMouseOut}
                onMouseMove={handleMouseOver}>
                {component}
            </span>
            <Tooltip
                x={tooltipXy.x}
                y={tooltipXy.y}
                content={tooltipContent}
                visible={tooltipVisible}
            />
        </li>
    );
};

const Todos = ({todos}) => (
    <ul>
        {todos.map((todo, index) => {
            const component = (
                <span style={{background: 'powderblue', display: 'inline'}}>
                    {todo.text}
                </span>
            );
            return (
                <Tooltipable
                    key={index}
                    component={component}
                    tooltipContent={'Created ' + todo.createdOn}
                />
            );
        })}
    </ul>
);

const App = () => {
    const todos = [
        {text: 'clean car', createdOn: 'yesterday'},
        {text: 'fix windows', createdOn: 'two days ago'},
        {text: 'go shopping', createdOn: 'today'},
        {text: 'meet family', createdOn: 'five days ago'},
        {text: 'clean car', createdOn: 'yesterday'},
        {text: 'fix windows', createdOn: 'two days ago'},
        {text: 'go shopping', createdOn: 'today'},
        {text: 'meet family', createdOn: 'five days ago'},
        {text: 'clean car', createdOn: 'yesterday'},
        {text: 'fix windows', createdOn: 'two days ago'},
        {text: 'go shopping', createdOn: 'today'},
        {text: 'meet family', createdOn: 'five days ago'},
        {text: 'clean car', createdOn: 'yesterday'},
        {text: 'fix windows', createdOn: 'two days ago'},
        {text: 'go shopping', createdOn: 'today'},
        {text: 'meet family', createdOn: 'five days ago'}
    ];
    return <Todos todos={todos} />;
};

ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html>

<head>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

</head>
  
<body>
  <div id="root">
</body>

</html>

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 2014-10-24
    • 2020-04-16
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    相关资源
    最近更新 更多