为什么在React的事件(例如onClick、onChange)的prop中不能写成”函数名()”?

首先

    • この記事ではReactアプリケーションでイベント(onClick、onChangeなど)のprop(コンポーネントの引数)の正しい渡し方について、サンプルを使いながら紹介します

 

    初歩的な内容ですが筆者の中で言語化出来ていなかった為、記事としました

这篇文章的受众是什么类型的人?

    • 現在Reactを学ばれている方

 

    これからReactを学ばれる方

行动环境

    • react-dom@18.2.0

 

    • react-scripts@5.0.1

 

    react@18.2.0

本文中使用的样本

以下示例是当点击“按钮1至按钮3”中的任意一个按钮时,将“0”部分逐渐加一的情况。

在这篇文章中提到的源代码可以通过在CodeSandbox的”App.js”文件中进行复制粘贴来进行确认运行。

 

那么,让我们进入正题吧。

对于样本,我们将添加以下功能作为额外实现。

    • ボタンnがクリックされた場合、「ボタンnがクリックされました!」というメッセージを「Hello」と書かれている部分に表示する

 

    ( 例:ボタン1がクリックされた場合、「Hello」 → 「ボタン1がクリックされました!」

NG模式

我在函数”func1″中添加了参数”n”,并追加了setMessage的处理。为此,我将按钮标签的prop设置为按钮编号作为参数的值。

import { useState } from "react";

export const App = () => {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState("Hello");

  const func1 = (n) => {
    setCount(count + 1);
    // messageを更新
    setMessage(`ボタン${n}がクリックされました!`);
  };

  return (
    <>
      <h1>{count}</h1>
      <p>{message}</p>  
      {/* func1に引数としてボタン番号を渡す */}
      <button onClick={func1(1)}>ボタン1</button>
      <button onClick={func1(2)}>ボタン2</button>
      <button onClick={func1(3)}>ボタン3</button>
    </>
  );
};
スクリーンショット 2023-07-23 19.41.35.png

这个错误简洁地表达为。

React君:“这个…一直在无限循环啊!!”

请注意以下部分,它调用了函数“func1”来处理上述的NG模式。

{/* func1に引数としてボタン番号を渡す */}
<button onClick={func1(1)}>ボタン1</button>

以下有两个要点。

    • 「関数名()」の形式で記述するとコンポーネントのレンダリング時に関数が実行される

 

    関数「func1」内ではステート(今回はcountとmessage)の値を変更しており、ステートが変更されるとコンポーネント(今回はApp.js)が再レンダリングされる

换句话说,导致无限循环的机制如下所示。

    • 画面レンダリング(1回目)

React君『関数「func1(1)」を実行するで〜』

関数「func1(1)」実行(1回目)

React君『countとmessageのステートを変更するで〜』

ステート変更(1回目)

React君「ステートが変わった!コンポーネントを再レンダリングするで〜」

画面レンダリング(2回目)

React君『関数「func1(1)」を実行するで〜』

関数「func1(1)」実行(2回目)

React君『countとmessageのステートを変更するで〜』



React君「これ…無限ループしてるで!!」

那要怎么办呢?(前面的谈话)

让我们在给出正确答案之前,回顾一下最初的示例调用方式,以及导致无限循环的错误调用方式,并进行比较。

{/* 無限ループしない(サンプル初期の呼び出し) */}
<button onClick={func1}>ボタン1</button>

{/* 無限ループする(NGパターンの呼び出し) */}
<button onClick={func1(1)}>ボタン1</button>

这两者的区别只是有无括号而已。
每个的返回值会怎么样呢?让我来解释一下,以便更容易理解。

{/* 無限ループしない(サンプル初期の呼び出し) */}
<button onClick={() => { return func1(); }}>ボタン1</button>

{/* 無限ループする(NGパターンの呼び出し) */}
<button onClick={ setCount(count + 1); setMessage(`ボタン1がクリックされました!`); }>ボタン1</button>

以“函数名”的形式编写,通过这种方式返回函数作为返回值。

与此相反,后者使用“函数名()”的形式来返回函数的执行结果。
由于只返回执行结果(没有返回值),即使无限循环没有错误并且按钮可以按下,也不会发生计数增加等情况。

React小伙伴:“哦!按钮被点击了!!我会处理onClick的操作…嗯,你只给我执行结果,不给我函数,我无法进行处理!”

那么我们应该怎么做呢?

如果你来到这里,应该就明白了。
在事件的prop中,我们要传递的是函数而不是函数的执行结果。

如果要直接修正NG模式的「onClick={func1(1)}」,那么修改如下。

<button onClick={() => { return func1(1); }}>ボタン1</button>

根据React官方文档,我们采用以下省略了大括号、return和分号的表达方式。这样变得更简单了。

<button onClick={() => func1(1)}>ボタン1</button>

所以,最终完成的源代码完整如下。

import { useState } from "react";

export const App = () => {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState("Hello");

  const func1 = (n) => {
    setCount(count + 1);
    setMessage(`ボタン${n}がクリックされました!`);
  };

  return (
    <>
      <h1>{count}</h1>
      <p>{message}</p>
      <button onClick={() => func1(1)}>ボタン1</button>
      <button onClick={() => func1(2)}>ボタン2</button>
      <button onClick={() => func1(3)}>ボタン3</button>
    </>
  );
};

如果在点击按钮时,“Hello”部分得到更新,那么就算成功了。太好了,太好了。

请提供更多的上下文。 “参考” 在不同的语境中有不同的意义。

 

总结

    • イベント(onClick、onChangeなど)のpropに「関数名()」の形式で書いてしまうと最悪の場合、無限ループしてアプリケーションが動かなくなってしまう

 

    イベントのpropには関数の実行結果ではなく、関数を渡そう
广告
将在 10 秒后关闭
bannerAds