เมื่อใดที่จะใช้องค์ประกอบการตอบสนองที่อิงคลาส ES6 กับการทำงานของส่วนประกอบการตอบสนอง ES6


212

หลังจากใช้เวลาในการเรียนรู้ทำปฏิกิริยาฉันเข้าใจความแตกต่างระหว่างกระบวนทัศน์หลักสองประการของการสร้างส่วนประกอบ

คำถามของฉันคือเมื่อฉันควรใช้ที่หนึ่งและทำไม สิทธิประโยชน์ / การแลกเปลี่ยนของหนึ่งเหนือสิ่งอื่นคืออะไร?


คลาส ES6:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

การทำงาน:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

ฉันคิดว่าการทำงานเมื่อใดก็ตามที่ไม่มีสถานะที่จะจัดการโดยองค์ประกอบนั้น แต่มันคืออะไร?

ฉันเดาว่าถ้าฉันใช้วิธีวงจรชีวิตใด ๆ มันอาจจะดีที่สุดที่จะไปกับองค์ประกอบตามระดับ


7
ดูเหมือนว่าคุณรู้คำตอบแล้ว
เฟลิกซ์คลิง

2
หากคุณมีส่วนประกอบที่มีวิธีการเรนเดอร์เท่านั้นคุณสามารถเปลี่ยนเป็นรูปแบบการทำงานได้ หากคุณต้องการอะไรมากกว่าฟังก์ชั่นการเรนเดอร์แบบไร้รัฐให้ใช้คลาส
just-boris

2
เพื่อความกระชับยิ่งขึ้นลองสิ่งนี้:const MyComponent = (props) => <div>...</div>
วิลเลียมซิมโก

1
ฉันไม่เคยใช้ฟังก์ชั่นหากสามารถหลีกเลี่ยงได้ เพราะท้ายที่สุดฉันก็จำเป็นที่จะต้องปรับโครงสร้างเพื่อให้ได้ตามระดับถนน แล้วมักจะต้อง refactor กลับไปทำงานหลังจากนั้น
keithjgrant

ในปี 2020 แนวทางที่ถูกต้องคือการใช้ส่วนประกอบที่ใช้งานได้ทุกที่ที่เป็นไปได้เพราะพวกมันรองรับ hooks และ hooks นั้นดีกว่าทางเลือกอื่น ๆ
polkovnikov.ph

คำตอบ:


161

คุณมีความคิดที่ถูกต้อง ไปพร้อมกับการใช้งานถ้าองค์ประกอบของคุณไม่ได้ทำอะไรมากไปกว่าอุปกรณ์ประกอบฉากและการแสดงผล คุณสามารถคิดว่าสิ่งเหล่านี้เป็นฟังก์ชั่นที่บริสุทธิ์เพราะพวกเขามักจะแสดงผลและประพฤติตนเหมือนเดิมโดยใช้อุปกรณ์ประกอบฉากเดียวกัน นอกจากนี้พวกเขาไม่สนใจวิธีการวงจรชีวิตหรือมีสถานะภายในของตัวเอง

เนื่องจากพวกมันมีน้ำหนักเบาการเขียนส่วนประกอบง่ายๆเหล่านี้เนื่องจากส่วนประกอบที่ใช้งานได้นั้นค่อนข้างมาตรฐาน

หากส่วนประกอบของคุณต้องการฟังก์ชั่นเพิ่มเติมเช่นรักษาสถานะให้ใช้คลาสแทน

ข้อมูลเพิ่มเติม: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


แก้ไข : ส่วนใหญ่ข้างต้นเป็นจริงจนกระทั่งการแนะนำ React Hooks

  • componentDidUpdateสามารถทำซ้ำด้วยuseEffect(fn)ซึ่งfnเป็นฟังก์ชั่นที่จะทำงานกับการแสดงผลซ้ำ

  • componentDidMountเมธอดสามารถจำลองแบบได้โดยuseEffect(fn, [])ที่fnฟังก์ชันจะทำงานตามการแสดงผลซ้ำและ[]เป็นอาร์เรย์ของออบเจกต์ที่ส่วนประกอบจะแสดงผลใหม่หากมีอย่างน้อยหนึ่งค่าที่เปลี่ยนแปลงตั้งแต่การเรนเดอร์ก่อนหน้า เมื่อไม่มีผู้ใช้useEffect()จะรันหนึ่งครั้งบนเมานต์แรก

  • stateสามารถจำลองแบบด้วยuseState()ซึ่งค่าส่งคืนสามารถถูกทำลายไปเป็นการอ้างอิงของสถานะและฟังก์ชันที่สามารถตั้งค่าสถานะ (เช่น, const [state, setState] = useState(initState)) ตัวอย่างอาจอธิบายสิ่งนี้ชัดเจนยิ่งขึ้น:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

เกี่ยวกับคำแนะนำเมื่อใช้ระดับมากกว่าส่วนประกอบการทำงาน, Facebook อย่างเป็นทางการแนะนำให้ใช้องค์ประกอบการทำงานเป็นไปได้ เล็ก ๆ น้อย ๆ ฉันเคยได้ยินคนพูดคุยกันหลายคนที่ไม่ได้ใช้ส่วนประกอบการทำงานเพื่อเหตุผลด้านประสิทธิภาพโดยเฉพาะ

"ฟังก์ชั่นการจัดการเหตุการณ์ถูกนิยามใหม่ต่อการแสดงผลในองค์ประกอบการทำงาน"

โปรดพิจารณาว่าองค์ประกอบของคุณแสดงผลด้วยความเร็วหรือระดับเสียงที่น่าเป็นห่วงหรือไม่

หากเป็นเช่นนั้นคุณสามารถป้องกันการกำหนดฟังก์ชั่นใหม่โดยใช้useCallbackและuseMemohooks แต่จำไว้ว่าเรื่องนี้อาจทำให้รหัสของคุณ (กล้องจุลทรรศน์) ที่เลวร้ายยิ่งในการปฏิบัติงาน

แต่จริงๆแล้วฉันไม่เคยได้ยินเรื่องการกำหนดฟังก์ชั่นใหม่เป็นคอขวดในแอป React การหาค่าเหมาะที่สุดก่อนกำหนดเป็นรากฐานของความชั่วร้ายทั้งหมด - กังวลเรื่องนี้เมื่อเกิดปัญหา


สิ่งที่เกี่ยวกับฟังก์ชั่นที่ไม่ได้รักษาสถานะไว้ แต่เชื่อมโยงกับส่วนประกอบอย่างแน่นหนาเช่นพิจารณาแอตทริบิวต์แบบไดนามิกบางอย่างสำหรับการแสดงผล
Dennis

นี่เป็นบทความที่ดีที่สุดเกี่ยวกับความแตกต่างระหว่างองค์ประกอบสองประเภทใน React: code.tutsplus.com/tutorials/…
Arian Acosta

5
ตั้งแต่ React 16.8 คุณสามารถใช้สถานะในองค์ประกอบที่ใช้งานได้ผ่านทางuseStatehook
Greg

ตั้งแต่ React 16.8 คุณสามารถทำเกือบทุกอย่างในส่วนประกอบที่ใช้งานได้และเอฟเฟกต์ทั้งหมดสามารถถูกทำให้เป็นโมดูลโดยมีผลกระทบต่อประสิทธิภาพน้อยที่สุด
polkovnikov.ph

1
ที่มีคุณหาข้อมูลที่Facebook officially recommends using functional components wherever possible?
johannchopin

40

พยายามใช้ฟังก์ชั่นไร้สัญชาติ (ส่วนประกอบที่ใช้งานได้) ทุกครั้งที่ทำได้ มีสถานการณ์ที่คุณจะต้องใช้คลาส React ปกติ:

  • องค์ประกอบต้องรักษาสถานะ
  • องค์ประกอบแสดงผลซ้ำมากเกินไปและคุณต้องควบคุมผ่าน shouldComponentUpdate
  • คุณต้องการส่วนประกอบคอนเทนเนอร์

UPDATE

ตอนนี้มีคลาส React ที่เรียกPureComponentว่าคุณสามารถขยาย (แทนComponent) ซึ่งใช้ของตัวเองshouldComponentUpdateที่ดูแลการเปรียบเทียบอุปกรณ์ประกอบฉากตื้น ๆ สำหรับคุณ อ่านเพิ่มเติม


43
Always try to use stateless functions (functional components) whenever possible.ฉันอ่านแล้วสิบคนพูดว่า ยังคงไม่มีใครอธิบายเหตุผลได้
Rotareti

25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.ข้อมูลเพิ่มเติม: facebook.github.io/react/docs/…
Diogo Cardoso

2
@rotareti ฉันไม่รู้ว่าคุณรู้สึกว่าคุณได้รับคำตอบจากคุณหรือไม่ แต่ฟังก์ชั่นที่บริสุทธิ์นั้นง่ายกว่ามากที่จะเข้าใจทดสอบและบำรุงรักษา เมื่อกำหนดพารามิเตอร์เดียวกันพวกมันจะทำสิ่งเดียวกันเสมอ ส่วนประกอบที่รักษาสถานะและการเปลี่ยนแปลงเมื่อเหตุการณ์รอบการทำงานเกิดขึ้นยากที่จะเข้าใจ ไม่ได้บอกว่าพวกเขาไม่จำเป็นต้องใช้บางครั้ง แต่ฉันหวังว่าเป็นที่ชัดเจนว่าหากไม่ต้องการใช้ข้อดีของพวกเขาสิ่งที่พวกเขาทำคือการเพิ่มหม้อไอน้ำและค่าใช้จ่ายที่ไม่พึงประสงค์โดยไม่มีประโยชน์
door_number_three

คุณจะต้องสร้างคลาส Component หากคุณมีคำจำกัดความตัวจัดการเหตุการณ์ของคุณเอง ด้วยวิธีนี้คุณสามารถผูกตัวจัดการเหตุการณ์เหล่านั้นล่วงหน้ากับคอมโพเนนต์ในตัวสร้างแทนการสร้างฟังก์ชั่นใหม่ในทุก ๆ การแสดงผล หมายเหตุไม่จำเป็นถ้าตัวจัดการเหตุการณ์ของคุณทั้งหมดมาจากอุปกรณ์ประกอบฉาก
Dobes Vandermeer

โปรดทราบว่าคำแนะนำ Facebook ที่ยกมาไม่มีอยู่อีกต่อไป (ดูความคิดเห็นของฉันด้านบน)
การ์เร็ตต์

34

อัพเดทมีนาคม 2562

https://overreacted.io/how-are-function-components-different-from-classes/

อัพเดทกุมภาพันธ์ 2562:

ด้วยการเปิดตัวReact hooksดูเหมือนว่าทีม React ต้องการให้เราใช้ส่วนประกอบการใช้งานทุกครั้งที่ทำได้ (ซึ่งเป็นไปตามลักษณะการทำงานของ JavaScript)

แรงจูงใจของพวกเขา:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

ส่วนประกอบที่ใช้งานได้กับ hooks สามารถทำเกือบทุกอย่างที่องค์ประกอบของคลาสสามารถทำได้

ฉันแนะนำให้ใช้พวกเขาโดยเร็วที่สุด

คำตอบเดิม

องค์ประกอบการทำงานไม่ได้มีน้ำหนักเบากว่าส่วนประกอบตามระดับ "พวกมันทำงานเหมือนกับคลาส" - https://github.com/facebook/react/issues/5677#issuecomment-241190513

ลิงค์ด้านบนเป็นวันที่เล็กน้อย แต่เอกสารของ React 16.7.0 ระบุว่าส่วนประกอบที่ใช้งานได้และคลาส:

"เทียบเท่าจากมุมมองของ React" - https://reactjs.org/docs/components-and-props.html#stateless-functions

โดยพื้นฐานแล้วไม่มีความแตกต่างระหว่างส่วนประกอบที่ใช้งานได้และองค์ประกอบของคลาสที่ใช้เมธอดการแสดงผลนอกเหนือจากไวยากรณ์

ในอนาคต (อ้างถึงลิงก์ด้านบน) "เรา [ตอบโต้] อาจเพิ่มประสิทธิภาพดังกล่าว"

หากคุณกำลังพยายามเพิ่มประสิทธิภาพโดยกำจัดการแสดงผลที่ไม่จำเป็นทั้งสองวิธีให้การสนับสนุน memoสำหรับส่วนประกอบที่ใช้งานได้และPureComponentสำหรับชั้นเรียน

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

มันขึ้นอยู่กับคุณจริงๆ ถ้าคุณต้องการแผ่นเหล็กให้น้อยลงให้ใช้งานได้ หากคุณรักการเขียนโปรแกรมที่ใช้งานได้และไม่ชอบคลาสให้ไปใช้งานได้ ถ้าคุณต้องการความสอดคล้องระหว่างส่วนประกอบทั้งหมดใน codebase ของคุณไปกับคลาส หากคุณเบื่อที่จะทำการปรับโครงสร้างใหม่จากการใช้งานไปยังส่วนประกอบตามระดับเมื่อคุณต้องการบางสิ่งstateให้ไปกับคลาส


1
ฉันคิดว่าการทำให้ทุกส่วนขยายเกิดขึ้นคอมโพเนนต์ทำให้โค้ดอ่านง่ายขึ้นโดยเฉพาะกับคนใหม่ เป็นเรื่องที่ดีเมื่อคุณเห็นองค์ประกอบที่สร้างขึ้นในลักษณะเดียวกันทุกครั้ง เช่นเดียวกับ @Galupuf กล่าวว่าส่วนประกอบอย่างง่ายมีวิธีการหนึ่งเดียวที่เรียกว่า "render ()" นอกจากนี้ยังเป็นการดีที่จะทำให้ทุกอย่างขยายไปถึง React.Component เพราะเมื่อคุณต้องการเริ่มผูกพัน "this" การมีสถานะ ฯลฯ คุณไม่จำเป็นต้อง refactor ทุกอย่างคุณสามารถเพิ่มสิ่งที่คุณต้องการได้
jeffski13

10

ในฐานะของ React 16.8 คำว่าไร้สัญชาติส่วนประกอบการทำงานจะทำให้เข้าใจผิดและควรหลีกเลี่ยงสาเหตุที่พวกเขาไม่ได้อีกต่อไปไร้สัญชาติ ( React.SFC เลิก , แดน Abramov ใน React.SFC ) พวกเขาสามารถมีรัฐที่พวกเขาสามารถมีตะขอ (การกระทำที่เป็น วิธีการวงจรชีวิต) เช่นกันพวกมันทับซ้อนกันมากขึ้นหรือน้อยลงด้วยองค์ประกอบระดับ

องค์ประกอบตามระดับ

  • สถานะ
  • วิธีการวงจรชีวิต
  • การบันทึกความจำด้วยReact.PureComponent

ฟังก์ชั่นส่วนประกอบ:

ทำไมฉันถึงชอบส่วนประกอบของ Funtional

  • ตอบสนองให้เบ็ด useEffect ซึ่งเป็นวิธีการอย่างชัดเจนและรัดกุมในการรวมcomponentDidMount, componentDidUpdateและcomponentWillUnmountวิธีวงจร
  • ด้วย hooks คุณสามารถแยกลอจิกที่สามารถแชร์ได้อย่างง่ายดายผ่านส่วนประกอบต่างๆและทดสอบได้
  • ความสับสนน้อยลงเกี่ยวกับการกำหนดขอบเขต

ตอบสนองต่อแรงจูงใจในการใช้ hooks (เช่นส่วนประกอบการทำงาน)

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