2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画面のレンダリング時に別の処理が走った

Posted at

はじめに

Reactで削除ボタンを実装していたときに、
「クリックした時に実行したい処理が、画面表示時に実行されてしまう」
という挙動に遭遇しました。

この記事では、

  • なぜその挙動が起きたのか
  • onClickを渡すときの書き方による違い

について整理します。

起きた問題

削除ボタンに以下のようなコードを書いていました。

<button onClick={deleteTodo(todo.id)}>
  削除
</button>

Todo削除する関数を実装完了!
この関数をonClickに渡せば、削除できると思って保存したら...

画面を表示した瞬間に削除処理が実行される

という挙動になりました。

原因は何だったのか?

今回の原因は、

  • 関数を「実行した結果」を渡していた
  • 関数そのものを渡せていなかった

という点でした。

言い換えると、
onClickには「後で実行する処理」を渡す必要があるのに、その場で処理を実行する書き方をしてしまっていました。

ではなぜ、そのような書き方になると「画面表示時に処理が実行される」のかという疑問を次の項目で説明します。

onClickに渡す書き方で何が変わるのか

onClick={deleteTodo(todo.id)}の場合

<button onClick={deleteTodo(todo.id)}>
  削除
</button>

一見すると、「削除ボタンをクリックしたらdeleteTodoが実行されそう」に見えます。

しかしこの書き方では、クリックとは関係なく、画面を表示する段階で処理が実行されます。

理由は、deleteTodo(todo.id)と書いた時点で、JavaScriptはこの関数をその場で実行してしまうからです。

そしてReactでは、画面を表示するためにJSXの中身が評価されます。

その評価の過程でdeleteTodo(todo.id)が実行されてしまうため、結果としてレンダリング(画面描画)時に削除処理が走ることとなります。

まとめると、deleteTodo(todo.id)と書いたことで、処理はクリック前に実行され、onClickには実行結果が渡っていました。

onClick={() => deleteTodo(todo.id)} の場合

<button onClick={() => deleteTodo(todo.id)}>
  削除
</button>

一見すると、先ほどのコードとほとんど同じように見えます。

しかしこの書き方では、画面を表示した時点では何も実行されません。

理由は、deleteTodo(todo.id)アロー関数の中に閉じ込めているからです。

この時点で作られているのは「削除処理そのもの」ではなく、クリックされた時に実行される関数です。

そのため、Reactが画面をレンダリングする際には処理は実行されず、ユーザーがクリックした瞬間に初めてdeleteTodoが実行されます。

まとめると、この書き方ではアロー関数を新しく作成し、「クリックされたら実行する処理」として、onClickに渡しています。

おわりに

最初は「Reactのレンダリングが原因?」と思いましたが、実際には JavaScriptの関数実行のタイミング の問題でした。

同じように「なぜかクリック前に処理が走る...」と悩んだ方の参考になれば嬉しいです。

※もし認識違いや、より良い書き方があれば、
ぜひコメントで教えてください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?