¿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!


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();

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>);
{

¿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

}

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>


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.


2

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

<a href="javascript: false" onClick={this.handlerName}>Click Me</a>

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

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


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}


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>

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!


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} />});
}

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;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.