¿Reaccionar onClick y preventDefault () actualización / redireccionamiento del enlace?

84

Estoy renderizando un enlace con react:

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

Entonces, arriba tengo la función upvote:

upvote: ->
  // do stuff (ajax)

Antes del enlace, tenía un intervalo en ese lugar, pero necesito cambiar al enlace y aquí está el problema: cada vez que hago clic en .upvotesla página se actualiza, lo que he intentado hasta ahora:

event.preventDefault () - no funciona.

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

event.stopPropagation () - no funciona.

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

return false - no funciona.

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

También probé todo lo anterior usando jQuery en mi index.html, pero nada parece funcionar. ¿Qué debo hacer aquí y qué estoy haciendo mal? He comprobado event.type y clicksupongo que debería poder evitar la redirección de alguna manera.

Disculpe, soy un novato cuando se trata de React.

¡Gracias!

Wordpressor
fuente
1
¿Está intentando utilizar la sintaxis es2015 para las funciones?
erichardson
¿Qué tipo de componentes estás creando? ¿Apátrida? createClass?
markthethomas
¿Puedes confirmar que onClick realmente está funcionando upvote? Este podría ser un problema de contexto.
thangngoc89
1
UsopreventDefault
onmyway133
1
e.PreventDefault () solo funcionó para mí (React 16.0.0-beta5)
felix-b

Respuestas:

68

Los eventos de reacción son en realidad eventos sintéticos, no eventos nativos. Como está escrito aquí :

Delegación de eventos: React no adjunta controladores de eventos a los propios nodos. Cuando React se inicia, comienza a escuchar todos los eventos en el nivel superior utilizando un solo detector de eventos. Cuando se monta o desmonta un componente, los controladores de eventos simplemente se agregan o eliminan de una asignación interna. Cuando ocurre un evento, React sabe cómo distribuirlo usando este mapeo. Cuando no quedan controladores de eventos en el mapeo, los controladores de eventos de React son simples no operativas.

Intente usar Use Event.stopImmediatePropagation:

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

Una versión completa de la solución incluirá el método upvotes dentro de onClick, pasando e y usando e.preventDefault () nativo;

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

render(){
    return (<a type="simpleQuery" onClick={ e => this.upvotes(e, arg1, arg2, arg3) }>
      upvote
    </a>);
{
romano
fuente
¿Hay alguna diferencia entre e.preventDefault (); estar al principio o al final de la función? ¿Dónde tiene más sentido colocarse?
Sartheris Stormhammer
Creo que es mejor usarlo al principio
Roman
Son malas prácticas, lea sobre las funciones de una flecha y el .bind(this)contexto del contenedor en una aplicación de reacción. Por ejemplo: medium.freecodecamp.org/…
Joyful
excepto que esto es solo crear una función para pasar el argumento. Si ya está usando react y ES6, no necesita la función con alcance. Y podría lograrlo fácilmente vinculándolo con esto en el constructor.
Iwnnay
Tenga en cuenta que si activa una representación (por ejemplo, cambiando el estado) antes de haber llamado a e.preventDefault (), no tendrá ningún efecto. Así que mejor tenerlo como primera declaración del controlador de eventos.
Thim Anneessens
16

intente vincular (esto) para que su código se vea a continuación:

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

o si está escribiendo en el componente de reacción es6 en el constructor, puede hacer esto

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

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

}
deepak prakash
fuente
9
Esto no hace ninguna diferencia. Obtienes votos positivos porque las personas tienen thisen su controlador de eventos y tienen un problema totalmente diferente.
Dimitar Nestorov
8

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

xjinjin
fuente
1
Son malas prácticas, lea sobre las funciones de una flecha y el .bind(this)contexto del contenedor en una aplicación de reacción. Por ejemplo: medium.freecodecamp.org/…
Joyful
createReactClass o Autobinding o use el paquete npm 'auto-bind'
xjinjin
6

En un contexto como este

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

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

Como puede ver, debe llamar a preventDefault () explícitamente. Creo que estos documentos podrían ser útiles.

Fabien Sartori
fuente
2

Una opción agradable y simple que funcionó para mí fue:

<a href="javascript: false" onClick={this.handlerName}>Click Me</a>
David
fuente
esto es tan subestimado. Quiero besarte si no te importa. me salvaste de muchas cosas señor. porque el elemento de formulario action="javascript: false"también está funcionando.
OzgurBagci
1
@OzgurBagci El uso del método anterior arrojará advertencias en React en versiones más recientes. Puede que funcione ahora, pero probablemente no funcione a largo plazo. Probablemente sea mejor encontrar un método alternativo, especialmente si usa una versión más actual de React.
David
1

Esto se debe a que esos controladores no conservan el alcance. De la documentación de reacción : documentación de reacción

Consulte la sección "sin enlace automático". Debe escribir el controlador como: onClick = () => {}

viktor
fuente
1

The Gist que encontré y funciona para mí:

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

Crédito para srph https://gist.github.com/srph/020b5c02dd489f30bfc59138b7c39b53

TheFullResolution
fuente
1
¿Puedo sugerir que no se use onClickcomo nombre de función de apoyo pasado, sino algo como en su handleClicklugar? Es confuso, otros desarrolladores con menos experiencia podrían pensar que es el evento adjunto real al componente, mientras que no lo es. Además, con esto, está creando una nueva función cada vez que el componente se vuelve a renderizar, incluso si recibe los mismos accesorios. Se considera una mala práctica.
elQueFaltaba
0

Si usa la casilla de verificación

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

stopPropagation y stopImmediatePropagation no funcionarán.

Porque debes usar onClick = {this.checkboxHandler}

romano
fuente
0

Si está utilizando React Router, le sugiero que busque en la biblioteca react-router-bootstrap que tiene un componente útil LinkContainer. Este componente evita la recarga de la página predeterminada para que no tenga que lidiar con el evento.

En su caso, podría verse algo como:

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

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

He tenido algunos problemas con las etiquetas de anclaje y preventDefaulten el pasado y siempre olvido lo que estoy haciendo mal, así que esto es lo que descubrí.

El problema que tengo a menudo es que trato de acceder a los atributos del componente destructurándolos directamente como con otros componentes de React. Esto no funcionará, la página se recargará , incluso con e.preventDefault():

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

Parece que la desestructuración causa un error ( Cannot read property 'href' of undefined) que no se muestra en la consola, probablemente debido a la recarga completa de la página. Dado que la función tiene un error, preventDefaultno se llama. Si el href es #, el error se muestra correctamente ya que no hay una recarga real.

Ahora entiendo que solo puedo acceder a los atributos como un segundo argumento de controlador en componentes personalizados de React, no en etiquetas HTML nativas . Entonces, por supuesto, para acceder a un atributo de etiqueta HTML en un evento, esta sería la forma:

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

¡Espero que esto ayude a otras personas como yo a desconcertarse por los errores que no se muestran!

DSav
fuente
0

No encontré que ninguna de las opciones mencionadas fuera correcta o funcionara para mí cuando llegué a esta página. Me dieron ideas para probar cosas y descubrí que esto funcionó para mí.

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

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

ninguno de estos métodos funcionó para mí, así que simplemente resolví esto con CSS:

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