อะไรคือความแตกต่างระหว่าง componentWillMount และ componentDidMount ใน ReactJS?


91

ฉันดูเอกสารของ Facebook ที่ ( React.Component ) และกล่าวถึงวิธีcomponentWillMountเรียกใช้บนไคลเอนต์ / เซิร์ฟเวอร์ในขณะที่componentDidMountเรียกใช้บนไคลเอนต์เท่านั้น อะไรcomponentWillMountทำเพื่อให้เซิร์ฟเวอร์หรือไม่

คำตอบ:


70

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

แทบไม่จำเป็นและไม่จำเป็นกับคลาส ES6 เลย


มันไม่เหมือนกับตัวสร้าง ในโหมดเข้มงวดใน dev เช่นตัวสร้างของคุณจะถูกเรียกสองครั้ง (สำหรับสองอินสแตนซ์ที่แตกต่างกัน) แต่จะมีเพียงตัวเดียวเท่านั้นที่มีชื่อ componentWillMount - stackoverflow.com/questions/61254372/…
adarsh

63

constructorวิธีการไม่ได้componentWillMountเช่นเดียวกับ

ตามที่ผู้เขียน Redux ระบุว่ามีความเสี่ยงที่จะส่งการดำเนินการจากตัวสร้างเนื่องจากอาจส่งผลให้เกิดการกลายพันธุ์ในขณะแสดงผล

อย่างไรก็ตามการส่งจากไปcomponentWillMountก็ทำได้ดี

จากปัญหา github :

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


แน่นอนว่ามันไม่ดีในทุกสถานการณ์ขึ้นอยู่กับสิ่งที่เกิดขึ้นcomponentXxxMountเช่น Ajax ในwillMountอาจทำให้เกิดปัญหาได้
Dave Newton

2
@DaveNewton ฉันไม่ได้บอกว่ามันดีในทุกสถานการณ์ ฉันเพิ่งยกตัวอย่างที่มีความแตกต่างเพื่อพิสูจน์ว่าคำตอบ "componentWillMount เป็นตัวสร้างโดยพื้นฐาน" นั้นผิด ขอบคุณที่ให้ความกระจ่าง
Liran Brimer

@LiranBrimer คำตอบนี้ไม่ถูกต้องเนื่องจาก componentWillMount เลิกใช้งานแล้วและจะหยุดทำงานใน 0.16 และ 0.17 ตามลำดับโดยเฉพาะอย่างยิ่งเกี่ยวกับ "อย่างไรก็ตามการส่งจาก componentWillMount ก็ใช้ได้" แถลงการณ์
Brian Webster

37

หากต้องการเพิ่มสิ่งที่ FakeRainBrigand กล่าวcomponentWillMountจะถูกเรียกเมื่อแสดงผล React บนเซิร์ฟเวอร์และบนไคลเอนต์ แต่componentDidMountจะเรียกเฉพาะบนไคลเอนต์เท่านั้น


10
componentWillMountจะเรียกบนเซิร์ฟเวอร์และไคลเอนต์ ดู: facebook.github.io/react/docs/…
David

1
@DaveNewton ยังไง ไม่ได้บอกว่าcomponentWillMountจะไม่เรียกลูกค้า
Ayush

7
@AyushShanker IMO สิ่งสำคัญคือต้องให้ข้อมูลที่ไม่ทำให้เข้าใจผิด โดยการไม่เปิดเผยอย่างชัดเจนจึงมีช่องว่างสำหรับการตีความที่ผิด: เอกสารมีความชัดเจน คุณถูกต้องที่ไม่ขัดแย้งอย่างชัดเจนเช่นกัน
Dave Newton

31

componentWillMountทำก่อน INITIAL renderของคอมโพเนนต์และใช้เพื่อประเมินอุปกรณ์ประกอบฉากและทำตรรกะพิเศษใด ๆ ตามนั้น (โดยปกติจะเป็นสถานะการอัปเดตด้วย) และด้วยเหตุนี้จึงสามารถดำเนินการบนเซิร์ฟเวอร์เพื่อให้ได้มาร์กอัปแสดงผลฝั่งเซิร์ฟเวอร์แรก .

componentDidMountจะดำเนินการหลังจากเริ่มต้นrenderเมื่อ DOM ได้รับการอัปเดต (แต่สิ่งสำคัญอย่างยิ่งก่อนที่การอัปเดต DOM นี้จะถูกทาสีลงในเบราว์เซอร์ทำให้คุณสามารถโต้ตอบขั้นสูงได้ทุกประเภทกับ DOM เอง) แน่นอนว่าสิ่งนี้สามารถเกิดขึ้นได้ในเบราว์เซอร์เท่านั้นและจะไม่เกิดขึ้นในฐานะส่วนหนึ่งของ SSR เนื่องจากเซิร์ฟเวอร์สามารถสร้างมาร์กอัปเท่านั้นไม่ใช่ DOM เองสิ่งนี้จะเกิดขึ้นหลังจากที่ส่งไปยังเบราว์เซอร์หากใช้ SSR

การโต้ตอบขั้นสูงกับ DOM ที่คุณพูด? Whaaaat ?? ... ใช่ - ณ จุดนี้เนื่องจาก DOM ได้รับการอัปเดตแล้ว (แต่ผู้ใช้ยังไม่เห็นการอัปเดตในเบราว์เซอร์) จึงเป็นไปได้ที่จะดักจับภาพวาดจริงไปยังหน้าจอโดยใช้window.requestAnimationFrameแล้วทำสิ่งต่างๆเช่นการวัดจริง องค์ประกอบ DOM ที่จะถูกส่งออกซึ่งคุณสามารถทำการเปลี่ยนแปลงสถานะเพิ่มเติมได้ซึ่งมีประโยชน์อย่างยิ่งเช่นการเคลื่อนไหวไปยังความสูงขององค์ประกอบที่มีเนื้อหาความยาวตัวแปรที่ไม่รู้จัก (ขณะนี้คุณสามารถวัดเนื้อหาและกำหนดความสูงให้กับภาพเคลื่อนไหวได้) หรือเพื่อหลีกเลี่ยงสถานการณ์จำลองเนื้อหาที่กะพริบในระหว่างการเปลี่ยนแปลงสถานะบางอย่าง

จงระวังให้มากแม้ว่าจะมีการเปลี่ยนแปลงของรัฐในยามใด ๆcomponentDid...เป็นอย่างอื่นอาจทำให้เกิดวง จำกัด เพราะการเปลี่ยนแปลงของรัฐจะยังเป็นสาเหตุอีกครั้งทำให้และด้วยเหตุนี้อีกcomponentDid...และในและในและใน


1
ฉันไม่คิดว่าการเพิ่มsetStateเข้ามาcomponentDidMountจะทำให้เกิดการวนซ้ำแบบไม่สิ้นสุด
Maddy

" เนื่องจากเป็นอย่างอื่นอาจทำให้เกิดการวนซ้ำแบบไม่สิ้นสุดเนื่องจากการเปลี่ยนแปลงสถานะจะทำให้เกิด re-render ด้วยและด้วยเหตุนี้จึงมี componentDidMount อื่นและ on and on and on " ซึ่งไม่เป็นความจริง แต่อย่างใด การเปลี่ยนแปลงสถานะจะทำให้เกิดการแสดงผลซ้ำ แต่จะไม่เรียกใช้componentDidMountซ้ำแล้วซ้ำอีก componentDidMount ถูกเรียกเพียงครั้งเดียวเมื่อคอมโพเนนต์ถูกเมาท์
hussain.codes

9

ตามเอกสาร ( https://facebook.github.io/react/docs/react-component.html )

วิธีการที่ขึ้นต้นด้วยพินัยกรรมถูกเรียกใช้ก่อนที่จะมีอะไรเกิดขึ้นและ

วิธีที่ขึ้นต้นด้วยdidเรียกว่า r ight หลังจากมีบางสิ่งเกิดขึ้น


2

componentWillMount https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/

แม้ว่าจะมี "gotcha": การเรียกแบบอะซิงโครนัสเพื่อดึงข้อมูลจะไม่กลับมาก่อนที่การแสดงผลจะเกิดขึ้น ซึ่งหมายความว่าส่วนประกอบจะแสดงผลด้วยข้อมูลว่างเปล่าอย่างน้อยหนึ่งครั้ง

ไม่มีวิธีใดที่จะ“ หยุดการแสดงผล” เพื่อรอให้ข้อมูลมาถึง คุณไม่สามารถคืนสัญญาจาก componentWillMount หรือ wrangle ใน setTimeout ได้

https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/birth/premounting_with_componentwillmount.html

ส่วนประกอบของเราจะไม่สามารถเข้าถึง Native UI (DOM ฯลฯ ) ได้ เราจะไม่สามารถเข้าถึงข้อมูลอ้างอิงของเด็ก ๆ ได้เนื่องจากยังไม่ได้สร้าง componentWillMount () เป็นโอกาสสำหรับเราในการจัดการการกำหนดค่าอัปเดตสถานะของเราและโดยทั่วไปเตรียมสำหรับการเรนเดอร์ครั้งแรก ซึ่งหมายความว่าเราสามารถเริ่มทำการคำนวณหรือประมวลผลตามค่า prop


1

กรณีใช้งานสำหรับ componentWillMount ()

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

componentWillMount() {
  this.setState({ todayDate: new Date(Date.now())});
}

กรณีการใช้งานสำหรับ componentDidMount ()

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

componentDidMount() {
  this.interval = setInterval(this.fetchNews, 3600000);
}

0

ComponentDidMount()เมธอดเปลี่ยนเฉพาะเพจปัจจุบันในคอมโพเนนต์คลาส แต่ComponentWillMount()เปลี่ยนเพจทั้งหมดที่ได้รับผลกระทบsetStates()

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