Reagieren Sie aufKlicken und verhindernDefault () Link aktualisieren / umleiten?

86

Ich rendere einen Link mit reagieren:

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

Dann habe ich oben die Upvote-Funktion:

upvote: ->
  // do stuff (ajax)

Vor dem Link hatte ich eine Zeitspanne an diesem Ort, aber ich muss zum Link wechseln und hier ist das Problem - jedes Mal, wenn ich auf .upvotesdie Seite klicke, wird aktualisiert, was ich bisher versucht habe:

event.preventDefault () - funktioniert nicht.

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

event.stopPropagation () - funktioniert nicht.

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

return false - funktioniert nicht.

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

Ich habe auch alle oben genannten Versuche mit jQuery in meiner index.html versucht, aber nichts scheint zu funktionieren. Was soll ich hier machen und was mache ich falsch? Ich habe event.type überprüft und es ist also clickso, dass ich in der Lage sein sollte, eine Umleitung irgendwie zu vermeiden?

Entschuldigung, ich bin ein Neuling, wenn es um Reagieren geht.

Vielen Dank!

Wordpressor
quelle
1
Versuchen Sie, die es2015-Syntax für die Funktionen zu verwenden?
erichardson30
Welche Art von Komponenten erstellen Sie? Staatenlos? createClass?
markthethomas
Können Sie bestätigen, dass onClick tatsächlich schlägt upvote? Dies könnte ein Kontextproblem sein.
Thangngoc89
1
Verwenden SiepreventDefault
onmyway133
1
e.PreventDefault () allein arbeitete für mich (React 16.0.0-beta5)
felix-b

Antworten:

69

Reaktionsereignisse sind eigentlich synthetische Ereignisse, keine nativen Ereignisse. Wie es geschrieben hier :

Ereignisdelegation: React hängt keine Ereignishandler an die Knoten selbst an. Wenn React gestartet wird, werden alle Ereignisse auf der obersten Ebene mit einem einzigen Ereignis-Listener abgehört. Wenn eine Komponente bereitgestellt oder nicht bereitgestellt wird, werden die Ereignishandler einfach zu einer internen Zuordnung hinzugefügt oder daraus entfernt. Wenn ein Ereignis auftritt, weiß React, wie es mithilfe dieser Zuordnung ausgelöst wird. Wenn im Mapping keine Ereignishandler mehr vorhanden sind, sind die Ereignishandler von React einfache No-Ops.

Versuchen Sie, Verwendung zu verwenden Event.stopImmediatePropagation:

upvote: (e) ->
  e.stopPropagation();
  e.nativeEvent.stopImmediatePropagation();
Alexandr Lazarev
quelle
74

Eine Vollversion der Lösung wird die Upvotes der Methode in onClick verpacken, e übergeben und native e.preventDefault () verwenden.

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

render(){
    return (<a type="simpleQuery" onClick={ e => this.upvotes(e, arg1, arg2, arg3) }>
      upvote
    </a>);
{
römisch
quelle
Gibt es einen Unterschied zwischen e.preventDefault (); am Anfang oder am Ende der Funktion sein? Wo ist es sinnvoller platziert zu werden?
Sartheris Stormhammer
Ich denke, es ist besser, es am Anfang zu verwenden
Roman
Es ist eine schlechte Praxis, bitte lesen Sie über eine Pfeilfunktion und .bind(this)für den Bin-Kontext in einer Reaktions-App. Zum Beispiel: medium.freecodecamp.org/…
Joyful
mit der Ausnahme, dass nur eine Funktion zum Übergeben des Arguments erstellt wird. Wenn Sie React und ES6 bereits verwenden, benötigen Sie die Gültigkeitsbereichsfunktion nicht. Und das können Sie genauso gut erreichen, indem Sie es im Konstruktor damit verbinden.
Iwnnay
Beachten Sie, dass das Auslösen eines Renderings (z. B. durch Ändern des Status) vor dem Aufruf von e.preventDefault () keine Auswirkungen hat. Also besser als erste Anweisung des Event-Handlers.
Thim Anneessens
16

Versuchen Sie bind (this), damit Ihr Code wie folgt aussieht:

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

oder wenn Sie in es6 reagieren Komponente im Konstruktor schreiben, können Sie dies tun

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

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

}
Deepak Prakash
quelle
9
Das macht keinen Unterschied. Sie erhalten positive Stimmen, weil die Leute thisin ihrem Event-Handler ein ganz anderes Problem haben.
Dimitar Nestorov
8

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

xjinjin
quelle
1
Es ist eine schlechte Praxis, bitte lesen Sie über eine Pfeilfunktion und .bind(this)für den Bin-Kontext in einer Reaktions-App. Zum Beispiel: medium.freecodecamp.org/…
Joyful
createReactClass oder Autobinding oder verwenden Sie das npm-Paket 'auto-bind'
xjinjin
6

In einem solchen Kontext

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

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

Wie Sie sehen, müssen Sie PreventDefault () explizit aufrufen. Ich denke, dass dieses Dokument hilfreich sein könnte.

Fabien Sartori
quelle
2

Eine schöne und einfache Option, die für mich funktioniert hat, war:

<a href="javascript: false" onClick={this.handlerName}>Click Me</a>
David
quelle
das ist sooo unterschätzt. Ich möchte dich küssen, wenn es dir nichts ausmacht. Sie haben mich vor vielen Dingen gerettet, Sir. denn das Formularelement action="javascript: false"funktioniert auch.
OzgurBagci
1
@OzgurBagci Wenn Sie die oben beschriebene Methode verwenden, werden in neueren Versionen Warnungen in React ausgegeben. Es kann jetzt funktionieren, wird aber wahrscheinlich längerfristig nicht funktionieren. Am besten finden Sie eine alternative Methode, insbesondere wenn Sie eine aktuellere Version von React verwenden.
David
1

Dies liegt daran, dass diese Handler den Gültigkeitsbereich nicht beibehalten. Aus der Reaktionsdokumentation: Reaktionsdokumentation

Überprüfen Sie den Abschnitt "Keine automatische Bindung". Sie sollten den Handler wie folgt schreiben: onClick = () => {}

viktor
quelle
1

Der Kern, den ich gefunden habe und der für mich arbeitet:

const DummyLink = ({onClick, children, props}) => (
    <a href="#" onClick={evt => {
        evt.preventDefault();
        onClick && onClick();
    }} {...props}>
        {children}
    </a>
);

Gutschrift für srph https://gist.github.com/srph/020b5c02dd489f30bfc59138b7c39b53

TheFullResolution
quelle
1
Darf ich vorschlagen, nicht onClickals übergebenen Prop-Funktionsnamen zu verwenden, sondern so etwas handleClick? Es ist verwirrend, andere weniger erfahrene Entwickler denken möglicherweise, dass es sich um das tatsächlich an die Komponente angehängte Ereignis handelt, während dies nicht der Fall ist. Außerdem erstellen Sie damit jedes Mal eine neue Funktion, wenn die Komponente erneut gerendert wird, auch wenn sie dieselben Requisiten erhält. Es wird als schlechte Praxis angesehen.
elQueFaltaba
0

Wenn Sie das Kontrollkästchen verwenden

<input 
    type='checkbox'
    onChange={this.checkboxHandler}
/>

stopPropagation und stopImmediatePropagation funktionieren nicht.

Weil Sie onClick = {this.checkboxHandler} verwenden müssen

römisch
quelle
0

Wenn Sie React Router verwenden, empfehlen wir Ihnen, in die React-Router-Bootstrap-Bibliothek zu schauen, die eine praktische Komponente LinkContainer enthält. Diese Komponente verhindert das erneute Laden von Standardseiten, sodass Sie sich nicht mit dem Ereignis befassen müssen.

In Ihrem Fall könnte es ungefähr so ​​aussehen:

import { LinkContainer } from 'react-router-bootstrap';

<LinkContainer to={givePathHere}>
    <span className="upvotes" onClick={this.upvote}>upvote</span>
</LinkContainer>
Iggirex
quelle
0

Ich hatte preventDefaultin der Vergangenheit einige Probleme mit Ankertags und vergesse immer, was ich falsch mache. Deshalb habe ich Folgendes herausgefunden.

Das Problem, das ich oft habe, ist, dass ich versuche, auf die Attribute der Komponente zuzugreifen, indem ich sie direkt wie bei anderen React-Komponenten destrukturiere . Dies wird nicht funktionieren, die Seite wird neu geladen , auch mit e.preventDefault():

function (e, { href }) {
  e.preventDefault();
  // Do something with href
}
...
<a href="/foobar" onClick={clickHndl}>Go to Foobar</a>

Es scheint, dass die Destrukturierung einen Fehler ( Cannot read property 'href' of undefined) verursacht, der der Konsole nicht angezeigt wird, wahrscheinlich aufgrund des vollständigen Neuladens der Seite. Da die Funktion fehlerhaft ist, wird die preventDefaultnicht aufgerufen. Wenn die href # ist, wird der Fehler korrekt angezeigt, da kein erneutes Laden erfolgt.

Ich verstehe jetzt, dass ich nur auf Attribute als Second-Handler-Argument für benutzerdefinierte React-Komponenten zugreifen kann, nicht für native HTML-Tags . Um auf ein HTML-Tag-Attribut in einem Ereignis zuzugreifen, ist dies natürlich der folgende Weg:

function (e) {
  e.preventDefault();
  const { href } = e.target;
  // Do something with href
}
...
<a href="/foobar" onClick={clickHndl}>Go to Foobar</a>

Ich hoffe, dies hilft anderen Leuten wie mir, verwirrt über nicht gezeigte Fehler zu sein!

DSav
quelle
0

Als ich zu dieser Seite kam, fand ich keine der genannten Optionen richtig oder funktionierte für mich. Sie gaben mir Ideen, um Dinge zu testen, und ich stellte fest, dass dies für mich funktionierte.

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

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

Keine dieser Methoden hat bei mir funktioniert, daher habe ich dies nur mit CSS gelöst:

.upvotes:before {
   content:"";
   float: left;
   width: 100%;
   height: 100%;
   position: absolute;
   left: 0;
   top: 0;
}
Suat Ağgez
quelle