สร้างโซลูชันการจัดการสถานะสำหรับบรรณาธิการของ Creative Tools

Nov 28 2022
บทนำ ในบทความนี้ เราจะแบ่งปันข้อมูลเชิงลึก (ที่มีความคิดเห็นเล็กน้อย) บางส่วนของเราเกี่ยวกับการออกแบบและสร้างโซลูชันการจัดการสถานะที่ปรับขนาดได้ในบริบทของโปรแกรมแก้ไขเครื่องมือสร้างสรรค์ที่มี React, Immer และ Recoil เป็นรากฐานของแนวทางของเรา เพื่ออธิบายแนวทางของเราได้ดียิ่งขึ้น เราจะรวมตัวอย่างโค้ดบางส่วนและต้นแบบขนาดเล็ก

บทนำ

ในบทความนี้ เราจะแบ่งปันข้อมูลเชิงลึก (ที่มีความคิดเห็นเล็กน้อย) บางส่วนของเราเกี่ยวกับการออกแบบและสร้างโซลูชันการจัดการสถานะที่ปรับขนาดได้ในบริบทของโปรแกรมแก้ไขเครื่องมือสร้างสรรค์ที่มี React, ImmerและRecoilเป็นรากฐานของแนวทางของเรา

เพื่ออธิบายแนวทางของเราได้ดียิ่งขึ้น เราจะรวมตัวอย่างโค้ดบางส่วนและต้นแบบขนาดเล็ก

เราใช้ความรู้นี้ในโปรเจกต์ที่แตกต่างกัน 2-3 โปรเจกต์ ทำให้เราสามารถหลีกหนีข้อผิดพลาดที่พบบ่อยที่สุดได้อย่างง่ายดาย

สถานะแอปเทียบกับสถานะการออกแบบ

ความแตกต่างหลักอย่างหนึ่งที่เราสร้างได้ในแอปประเภทนี้คือสถานะแอปเทียบกับสถานะการออกแบบ

สถานะการออกแบบ

อธิบายเนื้อหาที่ผู้ใช้สร้างขึ้น เช่น ข้อความ (แบบอักษร ขนาด สี เนื้อหา) รูปภาพ องค์ประกอบที่จัดกลุ่ม องค์ประกอบที่เชื่อมต่อ เป็นต้น

สถานะการออกแบบจะเปลี่ยนไปทุกครั้งที่แนวคิดการออกแบบเปลี่ยนแปลง แต่ไม่ใช่เมื่อผู้ใช้ดำเนินการที่ไม่ส่งผลกระทบต่อการออกแบบ

ตัวอย่างของการดำเนินการที่ส่งผลกระทบต่อสถานะการออกแบบ:

  • ย้ายองค์ประกอบ
  • เปลี่ยนคุณสมบัติของข้อความ (สี ขนาด แบบอักษร)
  • องค์ประกอบของกลุ่ม

กำหนดสถานะแอปปัจจุบัน ยกเว้นการออกแบบ สถานะของแอพจะเปลี่ยนไปเมื่อผู้ใช้โต้ตอบกับแอพและเมนูของพวกเขา

ตัวอย่างบางส่วน:

  • เลือกองค์ประกอบ
  • เปิดกล่องโต้ตอบเพื่อแก้ไขคุณสมบัติขององค์ประกอบ
  • แสดงเมนูคลิกขวา
  • ยืนยันการดำเนินการ

รัฐแต่ละประเภทมีลักษณะเฉพาะของตนเอง ซึ่งใช้ไม่ได้กับรัฐอื่นๆ และจะทำให้การดำเนินการของเราซับซ้อนมากขึ้นหากเก็บไว้ด้วยกัน

ตัวอย่างเช่น:

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

สถานะแอป

เมื่อใดก็ตามที่เราทำได้ เราต้องให้ความสำคัญกับสถานะท้องถิ่นมากกว่าสถานะส่วนกลาง สถานะแอปก็ไม่มีข้อยกเว้น

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

สถานะการออกแบบ

เมื่อกำหนดสถานะการออกแบบ เราต้องคำนึงถึงสิ่งต่อไปนี้:

  • สามารถรับและตั้งค่าสถานะทั้งหมดเพื่อให้เรานำไปใช้ได้อย่างง่ายดาย:
    – กำลังโหลดและบันทึกการออกแบบ
    – เลิกทำ/ทำซ้ำ
  • หลีกเลี่ยงการเรนเดอร์องค์ประกอบทั้งหมดเมื่อมีการเปลี่ยนแปลงเพียงบางส่วน

หนึ่งในวิธีที่ง่ายที่สุดในการปรับใช้การเลิกทำ/ทำซ้ำในแอปพลิเคชัน React คือการใช้ I mmerเพื่อสร้างแพตช์การแก้ไข

Immer เป็นไลบรารี JS ที่ช่วยให้เราสามารถเขียนการแก้ไขข้อมูลในบริบทที่ไม่เปลี่ยนรูป (เช่น สถานะ React) ใน "วิธีที่ไม่แน่นอน"

คุณสมบัติอีกอย่างของ Immer คือการสร้าง แพต ช์ do และ undo ของการแก้ไข ซึ่งช่วยให้เราสามารถบันทึกวิธีดำเนินการเปลี่ยนแปลงที่เราทำใหม่และวิธีย้อนกลับไปยังสถานะการแสดงตัวอย่าง

หลังจากการเปลี่ยนแปลงสถานะแต่ละครั้ง เราควรบันทึกแพตช์ do และ undo และใช้เมื่อผู้ใช้ทริกเกอร์การเลิกทำ/ทำซ้ำ

ทำไมเราต้องรับและตั้งค่าทั้งสถานะพร้อมกัน?

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

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

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

การใช้สถานะเดียวจะแก้ปัญหาเหล่านี้ได้ทั้งหมด

  • ไม่มีการกระทำใดที่ปรับเปลี่ยนหลายสถานะ
  • แพตช์ทั้งหมดใช้กับสถานะ ไม่ใช่กับสถานะแบบกระจายหลายสถานะ

วิธีที่ง่ายกว่าในการตอบสนองตัวเลือกการออกแบบนี้คือการบันทึกสถานะการออกแบบทั้งหมดไว้ในที่เดียวกัน นั่นอาจทำให้เราคิดอย่างuseState<DesignState>(defaultState)ที่คุณเดาได้ สิ่งนี้ทำให้เราล้มเหลวในการพิจารณา "เรนเดอร์แอปส่วนใหญ่":

ไม่แสดงผลแอปส่วนใหญ่เมื่อการออกแบบเปลี่ยนไป

เพื่อแก้ปัญหานี้ โดยทั่วไปเราใช้ Recoil ซึ่งเป็นไลบรารีการจัดการสถานะสำหรับ React

การหดตัวมีสองแนวคิดหลัก : อะตอมและตัวเลือก

อะตอม : หน่วยของรัฐที่สามารถนำมาใช้ในลักษณะที่คล้ายกับuseStateแต่ทั่วโลกเช่น

ในuseStateโค้ดข้างต้น DesignElements ทั้งหมดจะแสดงผลเมื่อใดก็ตามที่องค์ประกอบใด ๆ (หรือส่วนใดส่วนหนึ่งของสถานะ) เปลี่ยนแปลง เพื่อแก้ปัญหานี้ เราสามารถใช้ตัวเลือก

Selectors : ฟังก์ชันที่สร้างเส้นโครงจากอะตอมหรือตัวเลือกอื่นๆ เมื่อส่วนประกอบ React ใช้ตัวเลือก มันจะแสดงผลซ้ำเท่านั้น (มีข้อแม้บางประการ) เมื่อผลลัพธ์ของตัวเลือกเปลี่ยนไป

การหดตัวยังช่วยให้เราได้รับอาร์กิวเมนต์ในฟังก์ชันที่กำหนด Selector ซึ่ง Selector ประเภทนี้เรียกว่า SelectorFamily เราสามารถใช้สิ่งนี้เพื่อสร้าง selectorFamily ที่ได้รับ elementId และให้องค์ประกอบแก่เรา

เมื่อมีการแก้ไของค์ประกอบ โค้ดด้านบนจะทริกเกอร์การอัปเดต DesignElement ที่ตรงกันเท่านั้น และจะไม่แสดงองค์ประกอบทั้งหมดหรือส่วนประกอบการออกแบบ

ผู้สังเกตการณ์ที่เอาใจใส่อาจมองว่าองค์ประกอบการออกแบบจะแสดงผลเมื่อใดก็ตามที่มีการเพิ่มหรือลบส่วนประกอบ ซึ่งทริกเกอร์การแสดงผลใหม่ของ DesignElements ทั้งหมด หากสิ่งนี้ทำให้เกิดปัญหาด้านประสิทธิภาพสำหรับกรณีการใช้งานเฉพาะ เราสามารถรวมองค์ประกอบ DesignElement ไว้ในไฟล์React.memo.

ตั้งค่าสถานะ

เนื่องจากเราต้องการให้ชุดของเรานำไปใช้กับ DesignState ระดับบนสุด (เพื่อลดความซับซ้อนในการเลิกทำ/ทำซ้ำ) เราจึงสามารถสร้างการเรียกกลับ แบบหดตัว เพื่อสรุปตรรกะการปรับเปลี่ยนของเราและเลิกทำ/ทำซ้ำการสร้างแพตช์

ตัวอย่างขั้นต่ำสามารถพบได้ใน Codesanbox นี้

กำลังปิด

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

หากคุณอ่านมาจนถึงตรงนี้ ฉันอยากทราบความคิดเห็นของคุณ คุณสามารถติดต่อฉันได้ที่นี่

ที่ Zeppelin Labs เราช่วยผู้ก่อตั้งและบริษัทที่กำลังเติบโตในการทดลองและสร้างผลิตภัณฑ์ดิจิทัลที่แตกต่างซึ่งขับเคลื่อนการเติบโต คุณสามารถหาเราได้ที่นี่ หรือที่นี่ หรือที่นี่

หากคุณต้องการเข้าร่วมทีมกับเรา โปรดส่งอีเมลถึงเราที่[email protected]

ต้องการเป็นพันธมิตรหรือไม่? ส่งอีเมลถึงเราที่[email protected]

สมัครรับ จดหมายข่าวของเรา ที่นี่