React - 如何在合成事件被回收之前触发preventDefault()?

时间:2018-01-02 19:12:57

标签: reactjs preventdefault

我在React组件中有以下功能,该组件在单击链接时运行:

onClick(e, { name }) {
    e.stopPropagation();

    const doIt = await checkSomething();

    if (doIt) {
        e.preventDefault();
        doSomethingElse();
    }
}

问题是,到达e.preventDefault()时,合成事件将被回收。那么,如果需要一些逻辑来计算这个决定并且在合成事件被回收之前,如何告诉浏览器不要关注链接?

4 个答案:

答案 0 :(得分:2)

处理此问题的一种方法是使用preventDefault,当操作完成并且您需要路由时,请使用history.push()

自行调用路由逻辑
onClick(e, { name }) {
    e.stopPropagation();
    e.preventDefault();
    const doIt = await checkSomething();

    if (doIt) {
        doSomethingElse();
    } else {
        this.props.history.push('/pathToRoute');
    }
}

how to Programmatically navigate with React-router

上查看此答案

答案 1 :(得分:2)

我只是在这里提出一个想法。

如果您无法或不想以编程方式进行网址重定向,则可以选择其他方式。
只有在完成逻辑后,才可以嵌套函数(currying)并调用第二个函数 注意,这将要求您将嵌套函数编写为 IIFE

<小时/> 这是使用JavaScript(开放式控制台)的一个小概念证明:

&#13;
&#13;
const el = document.getElementById("link");


function onLinkClick() {
  console.log('doing some stuff..');
  for(let i = 0; i < 500; i++){
  	console.log(`doing more stuff #${i}`);  
  }
  return function(e) {
    // this will trigger with the actuall event (note this is an IIFE)
    console.clear();
  }();
}

el.addEventListener('click', onLinkClick);
&#13;
#big {
  min-height: 950px;
}
&#13;
<div id="big">
  <a id="link" href="#test">Click to get to the bottom of the page</a>
</div>

<div id="test">Bottom of page</div>
&#13;
&#13;
&#13;

反应示例:

&#13;
&#13;
class App extends React.Component {

  onClick = (e) => {
    console.log('doing some stuff..');
    for (let i = 0; i < 500; i++) {
      console.log(`doing more stuff #${i}`);
    }
    return ((e) => {
      //console.log(e, "inner function")
      console.clear();
    })(e)
  }

  render() {
    return (
      <div>
        <div style={{ height: '950px' }}>
          <a href="#test" onClick={this.onClick} >Click to get to the bottom of the page</a>
        </div>

        <div id="test">Bottom of page</div>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

要在事件上使用preventDefault,您需要在回调函数返回之前执行此操作。在完成异步任务后,您无法执行此操作。

如果你看MDN Event.preventDefault Notes,你会发现它说你必须在事件流程中的某个地方调用它。

  

在事件流的任何阶段调用preventDefault()会取消该事件,这意味着实例通常会因事件而采取的任何默认操作都不会发生。

您也可以参考这个问题:event.preventDefault in async functions 。在最上面的答案中,您会看到await的使用以及event.preventDefault()语句在第一个await语句之前需要如何发生。这适用于使用promises或任何异步操作。

暂且不说:

  

如果要以异步方式访问事件属性,则应在事件上调用event.persist(),这将从池中删除合成事件,并允许用户代码保留对事件的引用。

这是SyntheticEvent documentation

答案 3 :(得分:0)

您是否尝试过使用promise和.then():

// Async/Await
const asyncGreeting = async () => 'Greetings';

// Promises
const promiseGreeting = () => new Promise(((resolve) => {
  resolve('Greetings');
}));

asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));

您应该能够控制preventDefault();