React onClick和preventDefault()能防止链接刷新/重定向吗?

115

我正在使用React渲染一个链接:

render: ->
  `<a className="upvotes" onClick={this.upvote}>upvote</a>`

接下来,我在上面有一个点赞功能:

upvote: ->
  // do stuff (ajax)

在链接之前,我在那个位置有一个,但我需要切换到链接,这是问题所在——每次我点击.upvotes时,页面都会刷新。到目前为止,我尝试过的方法:

event.preventDefault() - 不起作用。

upvote: (e) ->
  e.preventDefault()
  // do stuff (ajax)

event.stopPropagation() - 不起作用。

upvote: (e) ->
  e.stopPropagation()
  // do stuff (ajax)

return false - not working.

upvote: (e) ->
  // do stuff (ajax)
  return false

我也尝试过在我的index.html中使用jQuery,但似乎没有任何效果。我应该怎么办以及我做错了什么?我已经检查了event.type,它是 click ,所以我想我应该能够以某种方式避免重定向?

对不起,当涉及到React时,我是个新手。

谢谢!


1
你是在尝试使用 ES2015 语法来编写函数吗? - erichardson30
你正在创建什么类型的组件?无状态组件?createClass? - markthethomas
你能确认一下 onClick 是否真的触发了“upvote”吗?这可能是一个上下文问题。 - thangngoc89
2
使用 preventDefault - onmyway133
1
e.PreventDefault() 在我的情况下起到了作用(React 16.0.0-beta5) - felix-b
显示剩余3条评论
15个回答

102

React事件实际上是合成事件而不是本地事件,正如此处所述:

  

事件委托:React实际上并没有将事件处理程序附加到节点本身。当React启动时,它使用单个事件侦听器在顶层监听所有事件。当组件被安装或卸载时,事件处理程序仅从内部映射中添加或删除。当事件发生时,React知道如何使用此映射调度它。当映射中没有事件处理程序时,React的事件处理程序只是无操作。

尝试使用 Event.stopImmediatePropagation

upvote: (e) ->
  e.stopPropagation();
  e.nativeEvent.stopImmediatePropagation();

3
2021年中的Event.stopPropagation。 - dclipca

94

完整版本的解决方案将把方法upvotes包装在onClick中,传递e并使用本机e.preventDefault();

upvotes = (e, arg1, arg2, arg3 ) => {
    e.preventDefault();
    //do something...
}

render(){
    return (<a type="simpleQuery" onClick={ e => this.upvotes(e, arg1, arg2, arg3) }>
      upvote
    </a>);
{

e.preventDefault(); 在函数的开头和结尾有区别吗?放在哪里更合适? - Sartheris Stormhammer
我认为最好在开始时使用它。 - Roman
这是一种不好的做法,请了解箭头函数和.bind(this)在React应用程序中绑定上下文。例如:https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56 - Joyful
除非这只是创建一个传递参数的函数。如果您已经在使用React和ES6,您不需要作用域函数。您可以通过在构造函数中绑定它来轻松实现。 - Iwnnay
请注意,如果在调用e.preventDefault()之前触发渲染(例如通过更改状态),它将不起作用。因此最好将其作为事件处理程序的第一条语句。 - Thim Anneessens

16

尝试使用 bind(this) 使您的代码像下面这样--

 <a className="upvotes" onClick={this.upvote.bind(this)}>upvote</a>

或者如果你在编写 ES6 React 组件的构造函数中,可以这样做:

constructor(props){
   super(props);
   this.upvote = this.upvote.bind(this);
}

upvote(e){   // function upvote
   e.preventDefault();
   return false

}

11
这并不影响。你之所以获得点赞是因为有人在他们的事件处理程序中使用了“this”,而且他们遇到了完全不同的问题。 - Dimitar Nestorov

10

在这样的情境下

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

正如你所看到的,你需要显式调用preventDefault()。

我认为这个文档可能会有所帮助。


它实际上起作用了!V17.0.2。 - Arvind K.

9

渲染:-> <a className="upvotes" onClick={(e) => {this.upvote(e); }}>点赞</a>


1
这是一种不好的做法,请了解箭头函数和.bind(this)在React应用程序中绑定上下文。例如:https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56 - Joyful
createReactClass或Autobinding或使用npm包'auto-bind' - xjinjin

3
我为自己找到了一个简单而好用的选项:
<a href="javascript: false" onClick={this.handlerName}>Click Me</a>

这个太被低估了。如果您不介意,我想亲吻您。您拯救了我很多事情,先生。对于表单元素action="javascript: false"也可以工作。 - Ozgur Bagci
3
使用上述方法在较新的 React 版本中会产生警告。它现在可能可以工作,但长期来看可能不会起作用。如果使用更当前的 React 版本,最好找到一种替代方法。 - David
此解决方案会出现以下警告(如David所述):react-dom.development.js:86 警告:React的未来版本将阻止javascript: URL作为安全预防措施。如果可以,请改用事件处理程序。如果需要生成不安全的HTML,请尝试使用dangerouslySetInnerHTML。React被传递了“javascript:false”。 - user3819197

2

当我来到这个页面时,我发现提到的选项都不正确或无法使用。它们确实给了我一些测试的想法,我发现这对我有效。

dontGoToLink(e) {
  e.preventDefault();
 }

render() {
  return (<a href="test.com" onClick={this.dontGoToLink} />});
}

2

1
我可以建议不要使用 onClick 作为传递的函数名称,而是像 handleClick 这样的名称?这很容易引起混淆,其他经验较少的开发者可能会认为它是组件实际附加的事件,但事实并非如此。另外,这样做会在每次组件重新渲染时创建一个新的函数,即使它接收相同的属性。这被认为是一种不好的做法。 - elQueFaltaba

1
这是因为那些处理程序不保留范围。来自React文档:React文档 请查看“无自动绑定”部分。您应该像这样编写处理程序:onClick =()=> {}

1
<button className="upvotes" onClick={this.upvote}>upvote</button>

如果你想执行Javascript脚本而不跳转到新页面,应该使用HTML 按钮

如果在a href中没有正确的地址,eslint会抛出以下错误:

href属性需要一个有效的值才能访问。请提供一个有效且可导航的地址作为href的值。如果无法提供有效的href,但仍需要元素看起来像链接,请使用一个按钮并使用适当的样式进行更改。

jsx-a11y/anchor-is-valid建议:

<a href="javascript:void(0)" onClick={foo}>Perform action</a>
<a href="#" onClick={foo}>Perform action</a>
<a onClick={foo}>Perform action</a>

All these anchor implementations indicate that the element is only used to execute JavaScript code. All the above should be replaced with:

<button onClick={foo}>Perform action</button>

相关:


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