Что такое logi c за функцией стрелка ведет себя по-разному при получении значений? - PullRequest
0 голосов
/ 03 мая 2020

У меня есть несколько вопросов о выражении функции стрелки в JSX. Вот пример кода, который обновляет content, когда происходит onClick.

const App = () => {
  const [content, setContent] = useState('click here');
  const mouseOnClick = () => {
    setContent('clicked');
  };
  return <h1 onClick={mouseOnClick}>{content}</h1>
}

Затем я попробовал различные выражения, чтобы увидеть, как он ведет себя

1. onClick={()=>mouseOnClick}
// does not fire

2. onClick={mouseOnClick()} 
// Infinitely renders

3. onClick={()=>mouseOnClick()}
// same as onClick={mouseOnClick} 

Однако, когда функция принимает значения, выражение ведет себя иначе, чем мои ожидания * делает?

Почему onClick={mouseOnClick} срабатывает один раз, когда onClick={mouseOnClick(id)} срабатывает бесконечно? Функционально ли onClick={mouseOnClick} и onClick={()=>mouseOnClick()} идентичны?

Ответы [ 8 ]

2 голосов
/ 04 мая 2020

Это на самом деле не проблема JSX. Это вопрос понимания того, что такое значение функции и что такое вызов функции .

Что такое значение функции?

В JavaScript функция является значением, аналогичным любому другому значению. Так же, как "foo" создает строковое значение, () => {} создает значение функции (точнее, функцию object ; также обратите внимание, что это одинаково для любого способа генерации функции: объявление функции, выражение функции , объявление метода, функция стрелки ... все это просто различные способы указать создание объекта функции).

В вашем примере mouseOnClick - это переменная, которая содержит функцию. Всякий раз, когда вы пишете mouseOnClick, вы ссылаетесь на этот функциональный объект. Обратите внимание, что ссылка на объект функции не вызывает функцию! (см. следующий раздел). Рассмотрим этот пример:

var foo = () => console.log('foo')
var bar = foo;

Здесь я присваиваю значение foo (функция) для bar. Сама функция не выполняется в этом процессе. То же самое происходит, когда вы передаете функцию в качестве параметра другой функции:

var foo = () => console.log('foo')
// Some hypothetical function bar
bar(foo)

В этом примере вызывается bar и ему передается значение foo (функция). Но функция в foo не вызывается.

Что такое вызов функции?

Чтобы вызвать функцию (значение), вы ставите () после него:

var foo = () => 42;

console.log(foo); // logs function object
console.log(foo()); // calls function and logs its return value

Конечно, вы можете передавать аргументы в функции, помещая их между ().

Как работает onClick?

Это работает аналогично всем API-интерфейсам обработки событий: onClick ожидает передачи функции value , которая затем может вызываться при возникновении события.


Итак, с учетом сказанного, давайте рассмотрим ваш пример:

  1. onClick={()=>mouseOnClick}

Это передает значение функции в onClick ( хорошо). Что делает функция? Это просто ссылки mouseOnClick (плохо). Мы знаем, что ссылка на функцию на самом деле не вызывает функцию.

onClick={mouseOnClick()}

Вызывает функцию (() после имени функции) и передает ее возвращаемое значение в onClick (плохо). Мы хотим вызвать mouseOnClick, когда событие происходит не тогда, когда компонент отображается.

onClick={()=>mouseOnClick()}

Передает значение функции в onClick (хорошо). Что делает функция? Он вызывает mouseOnClick (хорошо).

Теперь вы говорите, что функции / синтаксис будут вести себя по-разному, если ему будет передан аргумент. Но на самом деле это не так:

onClick={()=>mouseOnClick(id)}

То же, что и в случае 3, только с аргументом.

onClick={mouseOnClick(id)}

То же, что и в случае 2, только с аргументом.

1 голос
/ 03 мая 2020

То, что вы должны передать в onClick prop - это функция обратного вызова, которая будет вызываться после события onClick. () за функцией означает, что она будет вызвана. Итак:

  1. onClick={()=>mouseOnClick} Здесь вы создаете новую функцию, которая будет возвращать mouseOnClick определение функции. () отсутствует, поэтому он не будет работать.

  2. onClick={mouseOnClick} это правильный способ передачи обратного вызова без параметров. Вы только что передали функцию, которая должна запускаться после события. {mouseOnClick(id)} срабатывает бесконечно, потому что есть круглые скобки после функции - ведь это означает, что она будет автоматически вызываться при рендеринге вашего элемента, ваша функция изменяет состояние, вызывающее рендеринг - бесконечный рендеринг.

  3. По сути, это только одно: onClick={()=>mouseOnClick()} все время создает новую функцию, в то время как onClick={mouseOnClick} просто указывает на одну функцию.

Надеюсь, это было довольно ясно, и это помог тебе!

0 голосов
/ 03 мая 2020

Давайте рассмотрим все три случая по отдельности -:

  • Что такое логика c позади onClick = {() => mouseOnClick} не стреляя, а onClick = {() => mouseOnClick ()} делает?

    • Это перевод ES5. -:
      • onClick={()=>mouseOnClick} === onClick={ function () { return mouseOnClick }}
      • onClick={()=>mouseOnClick} === onClick={ function () { return mouseOnClick() }}
    • Первый случай - простая функция, которая возвращает ссылку на функцию.
    • Поскольку первый случай возвращает только ссылку на функцию и не вызывает никакой функции, то вызов функции не происходит, тогда как во втором случае функция фактически вызывается.

  • Почему onClick = {mouseOnClick} срабатывает один раз, когда onClick = {mouseOnClick (id)} срабатывает бесконечно?

    • Перевод для обоих случаев (что будет оба случая возвращаются к onClick) -:
      • onClick={mouseOnClick} === onClick={() => { setContent('clicked')}
      • onClick={mouseOnClick(id)} === onClick={mouseOnClick(id)} (direct function call).
    • Как мы видим, первый случай возвращает функцию тогда как второй случай возвращает прямой вызов функции, поэтому он вызывается бесконечно.

  • AreClick = {mouseOnClick} и onClick = {() => mouseOnClick ()} функционально идентичны?
    • Да, оба идентичны, давайте посмотрим, что они переводят: -
      • onClick={mouseOnClick} === onClick={() => { setContent('clicked')}
      • onClick={()=>mouseOnClick()} === onClick={// basically another function that calls mouseOnClick function }

Надеюсь, это поможет ...

0 голосов
/ 03 мая 2020

В первом случае вы определяете новую анонимную функцию и передаете ее как обработчик onClick. Сама функция ничего не делает, потому что внутри нее вы ничего не вызываете.

Во втором случае вы обновляете состояние во время рендеринга , когда вызываете mouseOnClick (id), что вызывает повторный рендеринг , поэтому вы попадаете в бесконечно l oop.

В третьем случае вы просто используете функцию-обертку, которая вызывает функцию mouseOnClick, что в некоторой степени эквивалентно вызову самой функции в качестве обработчика.

0 голосов
/ 03 мая 2020

Один из них вызывает mouseOnClick и передает возвращаемое значение в onClick. Так что onClick = undefined или что-нибудь еще возвращает mouseOnClick. Другой передает mouseOnClick как функцию в onClick. Поэтому он обычно вызывает mouseOnClick.

function mouseOnClick () {
  console.log("mouseOnClick called");
  return fn2;
}

function fn2 () {
  console.log("fn2 called");
}

function fn3 () {
  console.log('btn2.onclick === fn2', btn2.onclick === fn2);
  console.log('btn1.onclick === mouseOnClick', btn1.onclick === mouseOnClick);
}


btn1.onclick = mouseOnClick;   // onclick = fn1
btn2.onclick = mouseOnClick(); // fn1 => fn2, so onclick = fn2
// notice "fn1 called" in console.  it is called immediately and passed to btn2.onclick

btn3.onclick = fn3;
<button id="btn1">button</button>
<button id="btn2">button</button>

<button id="btn3">button</button>
0 голосов
/ 03 мая 2020

Q. Что логика c позади onClick = {() => mouseOnClick} не стреляет, а onClick = {() => mouseOnClick ()} делает?

Ans. ()=>mouseOnClick обозначает функцию, в которую вы возвращаете mouseOnClick. Этот тип возврата называется неявным возвратом. Это выражение не работает намеренно, потому что функция logi c никогда не вызывается. Но onClick={()=>mouseOnClick()} фактически запускает функцию, и именно поэтому она работает.

Q. Почему onClick = {mouseOnClick} срабатывает один раз, когда onClick = {mouseOnClick (id)} срабатывает бесконечно?

Ans. onClick пытается вызвать функцию с событием click. mouseOnClick это просто функция. Но когда вы говорите onClick={mouseOnClick()}, вы просто вызываете функцию при первом рендеринге. Если onclick инициирует изменение состояния, тогда произойдет другой рендеринг, и onclick будет вызван снова. Следовательно, l oop бесконечно, поскольку mouseOnClick и render продолжают вызывать друг друга снова и снова.

Q. Являются ли onClick = {mouseOnClick} и onClick = {() => mouseOnClick ()} функционально идентичными?

Ans. Логически да. но когда вы говорите onClick={()=>mouseOnClick()}, тогда onClick присваивает новую функцию при каждом рендеринге, который, по сути, сохраняет вызовы mouseOnClick. В другом случае это не так, т. Е. При каждом рендере onClick останется неизменным. Это может повлиять на производительность иногда, когда вы отправляете встроенную функцию в реквизит, и это может привести к ненужной визуализации дочернего элемента, потому что он будет продолжать получать новую функцию при каждом родительском рендеринге.

0 голосов
/ 03 мая 2020

Из моего ограниченного понимания JSX вы смешиваете обратные вызовы и возвращаемые значения

Допустим, что это ваша функция обратного вызова

function func(arg) {
    return arg * 2;
}

Если вы передадите эту функцию следующим образом он сразу же выполнит его и передаст возвращаемое значение событию onClick

<h1 onClick={func()}>{content}</h1>

Если вы оберните это внутри функции стрелки, оно будет ожидать выполнения до тех пор, пока не будет запущено событие onClick

<h1 onClick={()=>{func()}}>{content}</h1>

Если вы передадите только имя функции, она будет ждать его выполнения, пока не будет запущен onClick, и также передаст ему событие

<h1 onClick={func}>{content}</h1>

Если вы хотите передать аргумент своей функции, вы должны либо оберните его в функцию со стрелкой, например,

<h1 onClick={() => {func(arg)}}>{content}</h1>

или не передавайте ее вообще и создайте / опишите ее внутри функции

function func() {
    let arg = retrieveValueFromSomething();
    return arg * 2;
}
<h1 onClick={func}>{content}</h1>
0 голосов
/ 03 мая 2020

Здесь вы передаете onClick не функцию, а результат от функции (вы вызываете функцию в {} скобках)

2. onClick={mouseOnClick(id)} 

И здесь вы передаете ссылку на функцию

onClick={mouseOnClick} and onClick={()=>mouseOnClick()} 

React ожидает получить функцию, которая будет вызываться при срабатывании события click.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...