Cara terbaik untuk melewatkan parameter di penangan onClick

11

Ini adalah komponen saya, saya menggunakan fungsi panah sebaris untuk mengubah rute onClickdiv tetapi saya tahu itu bukan cara yang baik dalam hal kinerja

1. Fungsi panah sebaris

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={() => this.changeRoute("page1")}>1</div>
      <div onClick={() => this.changeRoute("page2")}>2</div>
    </>
  )
}

2. Jika saya menggunakan binding konstruktor maka bagaimana saya bisa lulus alat peraga?

constructor() {
  super(props)
  this.changeRoute = this.changeRoute.bind(this)
}
changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute}>1</div>
      <div onClick={this.changeRoute}>2</div>
    </>
  )
}

3. Jika saya menghapus fungsi panah maka fungsi dipanggil pada render itu sendiri

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute("page1")}>1</div>
      <div onClick={this.changeRoute("page2")}>2</div>
    </>
  )
}

4. Jika saya menggunakan inline binding maka itu juga tidak terbaik dengan kinerja

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute.bind(this, "page1")}>1</div>
      <div onClick={this.changeRoute.bind(this, "page2")}>2</div>
    </>
  )
}

Lalu bagaimana saya bisa melanjutkan dengan cara terbaik melewati parameter?

Kesatria Kegelapan
sumber
Mungkin perlu dicatat bahwa alasan mengapa menggunakan fungsi panah sebaris di sini "bukan [cara] yang baik dalam hal kinerja" bukan karena fungsi panah entah bagaimana pada dasarnya lambat untuk dijalankan (tidak, dan dalam hal apapun, biaya pemanggilan fungsi benar-benar dapat diabaikan untuk sesuatu yang jarang dieksekusi sebagai penangan klik) tetapi karena Bereaksi akan membuat instance fungsi baru setiap kali komponen dirender ulang. Ikatan sebaris memiliki masalah yang sama persis. Dan biasanya baik pula, kecuali komponen mendapat re-diberikan sangat sering.
Ilmari Karonen
2
@IlmariKaronen Dalam sebagian besar kasus, komponen sering dirender ulang karena komponen memiliki bidang input dan mengetik & mengatur e.target.value dalam status menghasilkan sering render.
Dark Knight

Jawaban:

6

Anda dapat menggunakan fungsi panah untuk menentukan changeRoute handler .

Ini dikenal sebagai Class field syntax. Lebih lanjut tentang ini di sini di dokumen reaksi resmi.

constructor() {
  super(props)
}

const changeRoute = (parameter) => (event) => {
    // business logic for route change.
}

Maka Anda dapat menggunakan fungsi ini secara langsung seperti:

render() {
  return (
    <>
      <div onClick={changeRoute(params1)}>1</div>
      <div onClick={changeRoute(params2)}>2</div>
    </>
  )
}

Anda tidak perlu khawatir tentang pengikatan. Fungsi panah mewarisi milik orang tua mereka this.

Utsav Patel
sumber
@DarkKnight Komentar terakhir Anda adalah executing on the go. Jawaban saya adalah menanggapi hal itu. Saya mencoba memberi tahu Anda bahwa penangan klik tidak akan melakukannya execute on the gojika Anda menetapkan penangan seperti yang telah saya kirim .
Utsav Patel
Tolong periksa ini
Dark Knight
@DarkKnight Silakan baca ini reactjs.org/docs/handling-events.html Sintaks bidang kelas adalah salah satu metode yang direkomendasikan oleh dokumen reaksi resmi.
Utsav Patel
ok terima kasih pak
Ksatria Kegelapan
3

Anda dapat menambahkan data ke div Anda:

<div data-id={1} onClick={this.changeRoute}>1</div>

Kemudian Anda dapat mengambil data itu di handler onClick Anda:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}
HermitCrab
sumber
Pendekatan yang brilian!
Maks
Ha ha ha ... Bisa dilakukan. Tapi reaksinya sendiri tidak berhasil?
Dark Knight
1

# 1 baik-baik saja.

# 2 juga 'baik', tetapi Anda harus melewati alat peraga, maka fungsi render akan terlihat persis seperti # 1 . Anda akan memanggil bindfungsi d, karena Anda menggantinya di konstruktor.

# 3 salah, karena fungsi dipanggil saat render.

Dan mengenai # 4, dari dokumen reaksi

Kami umumnya merekomendasikan mengikat di konstruktor atau menggunakan sintaks bidang bidang, untuk menghindari masalah kinerja semacam ini.

Ini menyebabkan penalti kinerja ketika fungsi Anda digunakan dalam komponen turunannya dan akan menyebabkan komponen turunan ulang (tidak ada dalam kasus Anda). Jadi Anda tidak harus melakukan # 4 .

Ben B
sumber
1

Cara terbaik saat ini adalah dengan membungkus event handler Anda di useCallbackhook karena itu akan mencegah fungsi handler Anda dibuat setiap kali render dipanggil.

import React, { useCallback } from 'react'

const MyComponent = ({ changeRoute }) => {
  const eventHandler = useCallback(() => {
    changeRoute('page1')
  }, [changeRoute])

  return (
    <div onClick={eventHandler}>1</div>
  )
}

Untuk info lebih lanjut, periksa - useCallback docs

Aleh Atsman
sumber
OP akan tampak menggunakan komponen kelas, di mana Anda tidak dapat menggunakan kait.
TJ Crowder
Saya harap jawaban saya akan membantunya memahami cara yang lebih baik
Aleh Atsman