วิธีที่ดีที่สุดในการส่งผ่านพารามิเตอร์ในตัวจัดการ onClick


11

นี่คือองค์ประกอบของฉันฉันใช้ฟังก์ชั่นลูกศรแบบอินไลน์เพื่อเปลี่ยนเส้นทางonClickของ div แต่ฉันรู้ว่ามันไม่ได้เป็นวิธีที่ดีในแง่ของประสิทธิภาพ

1. ฟังก์ชั่นลูกศรแบบอินไลน์

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

2. ถ้าฉันใช้ตัวสร้างการเชื่อมโยงฉันจะส่งผ่านอุปกรณ์ประกอบฉากได้อย่างไร

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. ถ้าฉันลบฟังก์ชั่นลูกศรแล้วฟังก์ชั่นที่ถูกเรียกบนการแสดงผลเอง

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

4. ถ้าฉันใช้การโยงแบบอินไลน์แล้วมันก็ไม่ได้ดีที่สุดกับประสิทธิภาพ

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>
    </>
  )
}

จากนั้นฉันจะดำเนินการวิธีส่งพารามิเตอร์ที่ดีที่สุดได้อย่างไร


อาจเป็นที่น่าสังเกตว่าสาเหตุที่การใช้ฟังก์ชั่นลูกศรแบบอินไลน์ที่นี่ "ไม่ใช่วิธีที่ดีในแง่ของประสิทธิภาพ" ไม่ใช่เพราะฟังก์ชั่นลูกศรจะทำงานช้ามาก ๆ ค่าใช้จ่ายของการเรียกใช้ฟังก์ชั่นนั้นเล็กน้อยมากสำหรับบางสิ่งที่ถูกเรียกใช้งานเป็นตัวจัดการคลิก) แต่เนื่องจาก React จะสร้างอินสแตนซ์ใหม่ของฟังก์ชั่นทุกครั้งที่มีการแสดงองค์ประกอบใหม่ การโยงแบบอินไลน์มีปัญหาเดียวกันแน่นอน และมันก็มักจะใช้ได้อยู่ดีเว้นแต่ว่าองค์ประกอบนั้นจะถูกเรนเดอร์ซ้ำบ่อยครั้งมาก
Ilmari Karonen

2
@IlmariKaronen ในกรณีส่วนใหญ่องค์ประกอบ re-renders บ่อยเพราะส่วนประกอบมีช่องใส่และการพิมพ์และการตั้งค่า e.target.value ในสถานะผลในการแสดงผลบ่อย
Dark Knight

คำตอบ:


6

คุณสามารถใช้ฟังก์ชั่นลูกศรเพื่อกำหนดchangeRouteตัวจัดการของคุณ

Class field syntaxนี้เป็นที่รู้จักกัน เพิ่มเติมได้ที่นี่ในเอกสารตอบโต้อย่างเป็นทางการ

constructor() {
  super(props)
}

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

จากนั้นคุณสามารถใช้ฟังก์ชั่นนี้ได้โดยตรงเช่น:

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

คุณไม่ต้องกังวลกับการผูกมัด thisลูกศรฟังก์ชั่นได้รับมรดกของพ่อแม่ของพวกเขา


@DarkKnight executing on the goความคิดเห็นล่าสุดของคุณเป็น คำตอบของฉันคือการตอบสนองต่อสิ่งนั้น ฉันพยายามที่จะบอกคุณว่าตัวจัดการคลิกของคุณจะไม่execute on the goถ้าคุณกำหนดตัวจัดการเหมือนที่ฉันโพสต์
Utsav Patel

กรุณาตรวจสอบเรื่องนี้
Dark Knight

@DarkKnight โปรดอ่านreactjs.org/docs/handling-events.htmlไวยากรณ์ฟิลด์คลาสเป็นหนึ่งในวิธีที่แนะนำโดยเอกสารตอบกลับอย่างเป็นทางการ
Utsav Patel

โอเคขอบคุณครับคุณ
Dark Knight

3

คุณสามารถเพิ่มข้อมูลลงใน div ของคุณ:

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

จากนั้นคุณสามารถดึงข้อมูลนั้นในตัวจัดการ onClick ของคุณ:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}

วิธีการที่ยอดเยี่ยม!
สูงสุด

ฮ่า ๆ ๆ ... สามารถทำได้ แต่ปฏิกิริยาที่ตัวเขาเองไม่ได้ทำอยู่เหรอ?
Dark Knight

1

# 1ไม่เป็นไร

# 2ยังเป็น 'ดี' แต่คุณต้องผ่านพร็อพแล้วทำให้ฟังก์ชั่นจะมีลักษณะเหมือน# 1 คุณจะเรียกใช้bindฟังก์ชัน 'd เพราะคุณแทนที่ฟังก์ชันนี้ใน constructor

# 3ผิดปกติเนื่องจากฟังก์ชั่นถูกเรียกระหว่างแสดงผล

และเกี่ยวกับ # 4 จากเอกสารตอบโต้

โดยทั่วไปเราขอแนะนำให้ผูกในตัวสร้างหรือใช้ไวยากรณ์คลาสฟิลด์เพื่อหลีกเลี่ยงปัญหาการจัดเรียงนี้

สิ่งนี้ทำให้เกิดการลงโทษประสิทธิภาพเมื่อฟังก์ชั่นของคุณใช้ในองค์ประกอบย่อยและจะทำให้องค์ประกอบย่อยแสดงผลอีกครั้ง (ไม่ใช่ในกรณีของคุณ) ดังนั้นคุณไม่ควรทำ# 4


1

วิธีที่ดีที่สุดในขณะนี้คือการห่อตัวจัดการเหตุการณ์ของคุณไว้ในuseCallbackตะขอเพราะจะป้องกันไม่ให้ฟังก์ชันตัวจัดการของคุณถูกสร้างขึ้นในแต่ละครั้งที่มีการเรียกเรนเดอร์

import React, { useCallback } from 'react'

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

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

สำหรับการตรวจสอบข้อมูลเพิ่มเติม - useCallback docs


OP ดูเหมือนจะใช้องค์ประกอบของคลาสซึ่งคุณไม่สามารถใช้ hooks ได้
TJ Crowder

ฉันหวังว่าคำตอบของฉันจะช่วยให้เขาเข้าใจวิธีที่ดีกว่า
Aleh Atsman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.