React 16.9.0中的"javascript:;" href替代方案是什么?

18

更新到React 16.9.0后,我得到了像这样的大警告:

警告:未来版本的React将会阻止javascript: URL作为安全预防措施。如果可以,请改用事件处理程序。如果需要生成不安全的HTML,请尝试使用dangerouslySetInnerHTML。React被传递了“javascript:;”。

它来自于这样的代码:

const Component = ({someAction}) => (
  <a href="javascript:void(0)" onClick={someAction}>click me</a>
);

查看关于在HTML中使用JavaScript链接的“href”值应该使用哪个的StackOverflow问题,似乎大多数人都同意javascript:void(0)是最佳选择,但这在React 16.9.0中将不再可用。
仅仅替换为href="#"是有问题的,因为浏览器会滚动到页面顶部并更改显示的URL。特别是如果您使用哈希链接进行路由,则非常有问题。
我可以更新我的整个代码库以在每个事件处理程序中添加e.preventDefault();,但这似乎很难做到,特别是当事件处理程序是从Redux操作创建器或挂钩自动生成时。我不想要答案“只需在每个地方包含e.preventDefault();”!
此外,使用<button>意味着我必须处理许多不需要的应用样式。
所以我想知道:是否有任何与库React相关的解决方案,以获得一个工作的<a>链接,只触发没有副作用的操作?我希望尽可能少地更改代码并摆脱弃用警告。

2
如果你有很多链接是按钮,我会选择使用按钮方式。你甚至可以使用 div,但那需要一些辅助功能调整。 - Emile Bergeron
5
如果一个链接从未作为链接起作用,它应该被设计成按钮。 - lonesomeday
1
我的意思是有一些关于如何使按钮看起来像链接的答案(https://dev59.com/CXM_5IYBdhLWcg3wdy_z),但这似乎非常复杂,并涉及一些神秘的特定于浏览器的CSS。 - amoebe
1
不要将锚点用作按钮。这是语义标记和可访问性的不良实践。 - isherwood
3
已经有人开始怀疑React团队添加这个警告的决定了:https://github.com/facebook/react/pull/15047#issuecomment-521736797 - amoebe
显示剩余6条评论
2个回答

21

2
我已经阅读了这篇博客文章。但是我仍然面临着如何调用 e.preventDefault() 的问题。 - amoebe

4
我设计了这样一个组件:
import React, {useCallback} from 'react';

function AHrefJavascript({ children, onClick, ...props }) {
  const handleClick = useCallback(
    e => {
      e.preventDefault();
      return onClick(e);
    },
    [onClick]
  );

  return (
    <a href="#javascript" {...props} onClick={handleClick}>
      {children}
    </a>
  );
}

它将仅包装事件处理程序以创建一个新的事件处理程序,该处理程序还调用e.preventDefault()。 它将向href添加哈希链接,这不会触发弃用警告。 利用钩子的力量,仅在传入的处理程序更新时更改事件处理程序。 一个问题是在浏览器中仍然可以在新标签中打开此链接,因此它并不像使用javascript:void(0)的链接那样好,后者将防止这种情况发生。

它很容易使用,组件如下所示:

const Component = ({someAction}) => (
  <AHrefJavascript onClick={someAction}>click me</a>
);

也许可以在整个项目中将 a href="javascript:void(0)" 替换为 AHrefJavascript,然后在每个地方添加该组件的导入。最终,最好的选择可能是使用一个 <button>,并经过一系列步骤来去除所有不需要的样式。

1
一个仅用于调用 e.preventDefault() 的组件似乎有些过度,有时您也希望保留默认行为。虽然使用某种 Link 组件来管理不同的行为(如跟踪、路由、样式等)是个好主意。 - Emile Bergeron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接