React onClick and preventDefault () ссылка на обновление / перенаправление?


87

Я делаю ссылку с реакцией:

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)

return 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 04

1
Только e.PreventDefault () работал у меня (React 16.0.0-beta5)
felix-b

Ответы:


70

События React на самом деле являются синтетическими, а не собственными событиями. Как здесь написано :

Делегирование событий: React фактически не присоединяет обработчики событий к самим узлам. Когда React запускается, он начинает прослушивать все события на верхнем уровне, используя один прослушиватель событий. Когда компонент монтируется или размонтируется, обработчики событий просто добавляются или удаляются из внутреннего сопоставления. Когда происходит событие, React знает, как отправить его с помощью этого сопоставления. Когда в сопоставлении не осталось обработчиков событий, обработчики событий React не работают.

Попробуйте использовать Используйте Event.stopImmediatePropagation:

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

74

Полная версия решения будет заключать метод upvotes внутри 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 (); в начале или в конце функции? Где больше смысла размещать?
Сартерис Штормхаммер

Я думаю, что лучше использовать вначале
Роман

Это плохая практика, ознакомьтесь с функциями стрелок и .bind(this)контекстом bin в приложении для реагирования. Например: medium.freecodecamp.org/…
Joyful

за исключением того, что это просто создание функции для передачи аргумента. Если вы уже используете реакцию и ES6, вам не нужна функция с областью действия. И вы могли бы так же легко сделать это, связав его с this в конструкторе.
Iwnnay

Помните, что если вы активируете рендеринг (например, изменив состояние) до вызова e.preventDefault (), это не даст никакого эффекта. Так что лучше сделать его первым оператором обработчика событий.
Thim Anneessens

16

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

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

или если вы пишете компонент реагирования es6 в конструкторе, вы можете сделать это

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

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

}

9
Это не имеет значения. Вы получаете положительные голоса, потому что у людей есть thisобработчик событий, и у них совершенно другая проблема.
Димитар Несторов

8

визуализировать: -> <a className="upvotes" onClick={(e) => {this.upvote(e); }}>upvote</a>


1
Это плохая практика, ознакомьтесь с функциями стрелок и .bind(this)контекстом bin в приложении для реагирования. Например: medium.freecodecamp.org/…
Joyful

createReactClass или Autobinding или используйте пакет npm 'auto-bind'
xjinjin

7

В таком контексте

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

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

Как видите, вы должны явно вызвать preventDefault (). Я думаю, что эта документация может быть полезна.


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в качестве переданного имени функции опоры, а использовать что-то вроде handleClickэтого? Это сбивает с толку, другие менее опытные разработчики могут подумать, что это фактическое присоединенное к компоненту событие, хотя это не так. Кроме того, при этом вы создаете новую функцию каждый раз при повторном рендеринге компонента, даже если он получает те же свойства. Это считается плохой практикой.
elQueFaltaba

0

Если вы используете флажок

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

stopPropagation и stopImmediatePropagation не будут работать.

Потому что вы должны использовать onClick = {this.checkboxHandler}


0

Если вы используете React Router, я бы посоветовал изучить библиотеку react-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

точно так же, как чистый js do preventdefault: в классе вам нужно создать метод обработчика:

handler(event) {
    event.preventDefault();
    console.log(event);
}

-1

ни один из этих методов у меня не сработал, поэтому я решил это с помощью 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.