Зреагуйте onClick та запобігайтеDefault () посилання оновлення / перенаправлення?


84

Я відображаю посилання з реакцією:

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

Тоді, зверху, у мене є функція upvote:

upvote: ->
  // do stuff (ajax)

До посилання я мав пробіг у цьому місці, але мені потрібно перейти на посилання, і ось проблема - кожен раз, коли я натискаю на .upvotesсторінку, оновлюється те, що я намагався до цього часу:

event.preventDefault () - не працює.

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

event.stopPropagation () - не працює.

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

повернути false - не працює.

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

Я також спробував усе вищезазначене, використовуючи jQuery у своєму index.html, але, здається, нічого не працює. Що мені тут робити і що я роблю не так? Я перевірив event.type, і clickтому я думаю, мені слід було б якось уникнути перенаправлення?

Вибачте, я новачок, коли справа доходить до React.

Дякую!


1
ви намагаєтесь використовувати синтаксис es2015 для функцій?
erichardson30,

Який компонент ви створюєте? Без громадянства? createClass?
markthethomas

Чи можете ви підтвердити, що onClick насправді б'є upvote? Це може бути проблемою контексту.
thangngoc89

1
ВикористанняpreventDefault
onmyway133

1
e.PreventDefault () у мене працював лише один (React 16.0.0-beta5)
felix-b

Відповіді:


68

Події реакції насправді є синтетичними, а не природними подіями. Як тут написано :

Делегування подій: React насправді не приєднує обробники подій до самих вузлів. Коли React запускається, він починає прослуховувати всі події на верхньому рівні за допомогою одного прослуховувача подій. Коли компонент монтується або демонтується, обробники подій просто додаються або видаляються з внутрішнього відображення. Коли відбувається подія, React знає, як її відправити, використовуючи це відображення. Коли в відображенні не залишається обробників подій, обробники подій React - це прості операції.

Спробуйте використати Use Event.stopImmediatePropagation:

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

74

Повною версією рішення буде обгортання голосів методу всередині 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

Я думаю, що краще використовувати його на початку
Роман

Це погана практика. Будь ласка, прочитайте про функції зі стрілками та .bind(this)контекст bin у додатку для реагування. Наприклад: medium.freecodecamp.org/…
Радісне

за винятком того, що це просто створення функції для передачі аргументу. Якщо ви вже використовуєте реакцію та ES6, вам не потрібна функція масштабу. І ви можете так само легко досягти цього, пов’язавши це з цим у конструкторі.
Iwnnay

Пам'ятайте, що якщо ви ініціюєте рендеринг (наприклад, зміною стану) перед тим, як викликати e.preventDefault (), це не матиме ефекту. Тож краще мати це як перше твердження обробника подій.
Тім Аннессенс,

16

спробуйте прив'язати (this), щоб ваш код виглядав, як показано нижче -

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

або якщо ви пишете у конструкторі es6 response у конструкторі, ви можете це зробити

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

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

}

9
Це не має різниці. Ви отримуєте голоси за те, що люди мають thisобробник подій і мають зовсім іншу проблему.
Димитър Несторов

8

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


1
Це погана практика. Будь ласка, прочитайте про функції зі стрілками та .bind(this)контекст bin у додатку для реагування. Наприклад: medium.freecodecamp.org/…
Радісне

createReactClass або Autobinding або використовуйте пакет npm 'auto-bind'
xjinjin

6

У такому контексті

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

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

Як бачите, вам доведеться явно викликати prevenDefault (). Я думаю, що ці документи можуть бути корисними.


2

Приємним і простим варіантом, який працював у мене, було:

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

це ооочень недооцінено. я хочу поцілувати тебе, якщо ти не проти. ви врятували мене від багатьох речей, сер. для елемента форми action="javascript: false"також працює.
OzgurBagci

1
@OzgurBagci Використання вищенаведеного методу викличе попередження в React в більш пізніх версіях. Це може працювати зараз, але, ймовірно, не буде працювати довше. Можливо, найкраще знайти альтернативний метод, особливо якщо використовується більш актуальна версія React.
Девід


1

Суть, яку я знайшов і працює для мене:

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

Кредит для srph https://gist.github.com/srph/020b5c02dd489f30bfc59138b7c39b53


1
Чи можу я запропонувати не використовувати onClickяк передану назву функції prop, а щось на зразок handleClickцього? Це бентежить, інші менш досвідчені розробники можуть подумати, що це фактично прикріплена до компонента подія, тоді як це ні. Крім того, за допомогою цього ви створюєте нову функцію щоразу, коли компонент рендерірується, навіть якщо він отримує однакові властивості. Це вважається поганою практикою.
elQueFaltaba

0

Якщо ви використовуєте прапорець

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

stopPropagation та stopImmediatePropagation не працюватимуть.

Тому що ви повинні використовувати onClick = {this.checkboxHandler}


0

Якщо ви використовуєте React Router, я пропоную заглянути в бібліотеку response-router-bootstrap, яка має зручний компонент LinkContainer. Цей компонент запобігає перезавантаженню сторінки за замовчуванням, тому вам не доведеться мати справу з подією.

У вашому випадку це може виглядати приблизно так:

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

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

0

У мене були проблеми з прив'язкою тегів і preventDefaultв минулому, і я завжди забуваю, що роблю неправильно, ось ось що я зрозумів.

Проблема, яку я часто маю, полягає в тому, що я намагаюся отримати доступ до атрибутів компонента, деструктуруючи їх безпосередньо, як і з іншими компонентами React. Це не буде працювати, сторінка перезавантажиться , навіть якщо e.preventDefault():

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

Здається, деструктуризація викликає помилку ( Cannot read property 'href' of undefined), яка не відображається на консолі, ймовірно через повне перезавантаження сторінки. Оскільки функція помилкова, функція preventDefaultне викликається. Якщо href #, помилка відображається належним чином, оскільки фактичного перезавантаження немає.

Зараз я розумію, що я можу отримати доступ до атрибутів лише як другий аргумент обробника в користувацьких компонентах React, а не в рідних тегах HTML . Тож, звичайно, щоб отримати доступ до атрибута HTML-тегу в події, це буде таким чином:

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

Сподіваюся, це допоможе людям, таким як я, спантеличені не показаними помилками!


0

Коли я зайшов на цю сторінку, я не знайшов жодного із згаданих варіантів правильним і не працював для мене. Вони давали мені ідеї, щоб перевірити речі, і я виявив, що це спрацювало для мене.

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

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

0

жоден із цих методів не працював у мене, тому я просто вирішив це за допомогою CSS:

.upvotes:before {
   content:"";
   float: left;
   width: 100%;
   height: 100%;
   position: absolute;
   left: 0;
   top: 0;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.