ฉันทำงานกับ React
TLDR:
แต่คุณสามารถเชื่อถือ React เพื่ออัปเดตสถานะตามลำดับเดียวกับที่เรียกใช้ setState
ใช่.
ใช่.
เพื่อการปรับปรุงเป็นที่เคารพนับถือเสมอ ไม่ว่าคุณจะเห็นสถานะกลาง "ระหว่าง" หรือไม่ขึ้นอยู่กับว่าคุณอยู่ในกลุ่มหรือไม่
ปัจจุบัน (React 16 และก่อนหน้า), ปรับปรุงเฉพาะภายใน React จัดการเหตุการณ์จะเป็นแบทช์โดยค่าเริ่มต้น มี API ที่ไม่เสถียรในการบังคับใช้แบตช์นอกตัวจัดการเหตุการณ์สำหรับกรณีที่หายากเมื่อคุณต้องการ
ในเวอร์ชันต่อ ๆ ไป (อาจเป็น React 17 และใหม่กว่า) React จะรวมการอัปเดตทั้งหมดตามค่าเริ่มต้นดังนั้นคุณจะไม่ต้องคิดถึงเรื่องนี้ เช่นเคยเราจะประกาศการเปลี่ยนแปลงใด ๆ เกี่ยวกับเรื่องนี้ในบล็อก Reactและในบันทึกประจำรุ่น
กุญแจสำคัญในการทำความเข้าใจเกี่ยวกับเรื่องนี้ก็คือว่ากี่ไม่มีsetState()
สายในหลายวิธีที่คุณทำส่วนประกอบภายใน React จัดการเหตุการณ์ที่พวกเขาจะผลิตเพียงคนเดียวอีกครั้งทำให้ในตอนท้ายของเหตุการณ์ นี่เป็นสิ่งสำคัญสำหรับประสิทธิภาพที่ดีในแอปพลิเคชันขนาดใหญ่เพราะหากChild
และParent
แต่ละครั้งsetState()
เมื่อจัดการเหตุการณ์การคลิกคุณไม่ต้องการแสดงผลChild
ซ้ำสองครั้ง
ในทั้งสองตัวอย่างของคุณการsetState()
โทรเกิดขึ้นภายในตัวจัดการเหตุการณ์ตอบสนอง ดังนั้นจึงมักจะถูกล้างพร้อมกันเมื่อสิ้นสุดกิจกรรม (และคุณไม่เห็นสถานะกลาง)
การปรับปรุงอยู่เสมอรวมตื้นในลำดับที่พวกเขาเกิดขึ้น ดังนั้นหากการปรับปรุงครั้งแรกเป็น{a: 10}
ที่สองคือ{b: 20}
และที่สามเป็นของรัฐการแสดงผลจะเป็น{a: 30}
{a: 30, b: 20}
การอัปเดตล่าสุดสำหรับคีย์สถานะเดียวกัน (เช่นa
ในตัวอย่างของฉัน) จะ "ชนะ" เสมอ
this.state
วัตถุที่มีการปรับปรุงเมื่อเราอีกครั้งทำให้ UI ในตอนท้ายของแบทช์ ดังนั้นหากคุณต้องการเพื่อให้รัฐปรับปรุงอยู่บนพื้นฐานของรัฐก่อนหน้านี้ (เช่นการเพิ่มเคาน์เตอร์), คุณควรใช้การทำงานรุ่นที่ช่วยให้คุณรัฐก่อนหน้านี้แทนการอ่านจากsetState(fn)
this.state
หากคุณสงสัยเกี่ยวกับเหตุผลนี้ฉันได้อธิบายไว้ในเชิงลึกในความคิดเห็นนี้
ในตัวอย่างของคุณเราจะไม่เห็น "สถานะกลาง" เนื่องจากเราอยู่ในตัวจัดการเหตุการณ์ Reactที่เปิดใช้งานการแบตช์ (เนื่องจาก React "รู้" เมื่อเราออกจากเหตุการณ์นั้น)
อย่างไรก็ตามทั้งสองในการตอบสนอง 16 และรุ่นก่อนหน้ายังมีเครื่องผสมโดยนอกเริ่มต้นของการตอบสนองจัดการเหตุการณ์ไม่มี ดังนั้นหากในตัวอย่างของคุณเรามีตัวจัดการการตอบกลับ AJAX แทนhandleClick
แต่ละตัวsetState()
จะถูกประมวลผลทันทีที่เกิดขึ้น ในกรณีนี้ใช่คุณจะเห็นสถานะกลาง:
promise.then(() => {
this.setState({a: true});
this.setState({b: true});
this.props.setParentState();
});
เรารู้ว่ามันไม่สะดวกที่พฤติกรรมที่แตกต่างกันขึ้นอยู่กับว่าคุณอยู่ในตัวจัดการเหตุการณ์หรือไม่ สิ่งนี้จะเปลี่ยนไปในเวอร์ชัน React ในอนาคตซึ่งจะรวมการอัปเดตทั้งหมดตามค่าเริ่มต้น (และมี API ที่เลือกใช้เพื่อล้างการเปลี่ยนแปลงพร้อมกัน) จนกว่าเราจะเปลี่ยนพฤติกรรมเริ่มต้น (อาจอยู่ใน React 17) มี API ที่คุณสามารถใช้เพื่อบังคับใช้แบตช์ :
promise.then(() => {
ReactDOM.unstable_batchedUpdates(() => {
this.setState({a: true});
this.setState({b: true});
this.props.setParentState();
});
});
ตัวจัดการเหตุการณ์ที่ตอบสนองภายในทั้งหมดถูกรวมเข้าด้วยกันunstable_batchedUpdates
ซึ่งเป็นสาเหตุที่ทำให้พวกมันถูกรวมเป็นกลุ่มตามค่าเริ่มต้น โปรดทราบว่าการรวมการอัปเดตเป็นunstable_batchedUpdates
สองครั้งจะไม่มีผล การอัปเดตจะถูกล้างเมื่อเราออกจากunstable_batchedUpdates
สายนอกสุด
API นั้น "ไม่เสถียร" ในแง่ที่เราจะลบออกเมื่อเปิดใช้งานแบตช์โดยค่าเริ่มต้นแล้ว อย่างไรก็ตามเราจะไม่ลบออกในเวอร์ชันรองดังนั้นคุณสามารถวางใจได้อย่างปลอดภัยจนถึง React 17 หากคุณจำเป็นต้องบังคับใช้แบทช์ในบางกรณีนอกตัวจัดการเหตุการณ์ React
สรุปได้ว่านี่เป็นหัวข้อที่น่าสับสนเนื่องจากตอบสนองเฉพาะแบทช์ภายในตัวจัดการเหตุการณ์ตามค่าเริ่มต้น สิ่งนี้จะเปลี่ยนไปในเวอร์ชันต่อ ๆ ไปและพฤติกรรมจะตรงไปตรงมามากขึ้น แต่วิธีแก้ปัญหาคือไม่ต้องแบทช์น้อยลงแต่จะต้องแบทช์มากขึ้นตามค่าเริ่มต้น นั่นคือสิ่งที่เรากำลังจะทำ