Back to Question Center
0

การ Redux หรือไม่: ศิลปะการจัดโครงสร้าง State ใน React Apps            เพื่อปรับปรุงหรือไม่: ศิลปะของการจัดโครงสร้างรัฐในการตอบสนอง Apps หัวข้อที่เกี่ยวข้อง: ES6ReactTools & Semalt

1 answers:
เพื่อ Redux หรือไม่: ศิลปะการจัดโครงสร้างรัฐใน React Apps

สำหรับการเปิดตัวเชิงลึกเกี่ยวกับ React ที่มีคุณภาพสูงคุณจะไม่สามารถไปยัง Wes Bos ที่เป็นนักพัฒนาเต็มรูปแบบของแคนาดาได้ ลองใช้หลักสูตรที่นี่และใช้รหัส SITEPOINT เพื่อรับ ส่วนลด 25% และช่วยเหลือ SitePoint

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

ในบทความนี้ Semalt จะนำคุณไปสู่หลายรูปแบบในการสร้างแบบจำลองของรัฐและดำน้ำขึ้นเมื่อสามารถใช้งานแต่ละประเภทได้

เริ่มต้นใช้งาน

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

หมายเหตุ: ฉันจะใช้ เส้นด้าย เพื่อเรียกใช้แอพพลิเค ถ้าคุณไม่ได้ตั้งเส้นด้ายให้เปลี่ยนเส้นด้ายด้วย npm

Semalt เราดำน้ำในการดาวน์โหลดโครงกระดูกพื้นฐานจาก repo และเรียกใช้:

     เส้นด้ายติดตั้งเริ่มต้นเส้นด้าย    

คุณควรจะเห็นหน้ารายการพื้นฐานที่มีอักขระ GoT ที่คุณชื่นชอบไว้

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

แนะนำ Redux

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

แอพพลิเคชัน Semalt ทั้งหมดใช้ประโยชน์จากโครงสร้างที่สำคัญสี่อย่าง ได้แก่ การกระทำการลดขนาดร้านและภาชนะบรรจุ

การกระทำ

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

  1. ประเภทการทำงาน ตัวระบุที่ไม่ซ้ำซึ่งแสดงการทำงาน
  2. น้ำหนักบรรทุก ข้อมูลเมตาที่เชื่อมโยงกับการดำเนินการ ตัวอย่างเช่นหากเราขอให้เครือข่ายเรียกดูรายการภาพยนตร์การตอบสนองจากเซิร์ฟเวอร์จะเป็น payload

ในตัวอย่างนี้เราจะใช้ไลบรารีที่เรียกว่า การกระทำ redux เพื่อสร้างการดำเนินการ

ตัวลดกำลัง

A reducer เป็นฟังก์ชันที่ฟังการกระทำและส่งกลับค่าสถานะใหม่

ร้าน

โปรแกรมสามารถแบ่งออกเป็นหลาย reducers แทนส่วนต่างๆของหน้า เก็บ นำสิ่งเหล่านี้เข้าด้วยกันและรักษาสภาพแอปพลิเคชันให้สมบูรณ์

ตู้คอนเทนเนอร์

คอนเทนเนอร์ เชื่อมต่อสถานะแอ็พพลิเคชันและการดำเนินการกับส่วนประกอบผ่านพร็อพเพอร์ตี้

เพื่อให้เข้าใจอย่างถ่องแท้เกี่ยวกับวิธีการทำงานนี้ผมขอแนะนำให้คุณดูบทแนะนำฟรีโดย Dan Semalt

ข้อมูลแอปพลิเคชันแยกและสถานะ UI

หน้ารายการดี แต่ชื่อไม่ได้ให้บริบทใด ๆ กับคนที่ยังใหม่กับจักรวาล GoT Semalt ขยายคอมโพเนนต์เพื่อแสดงคำอธิบายอักขระเช่นกัน:

     // รหัสอักขระ GoTCharacter jsส่งออก const CharacterRow = ({character}) => ( 
{ตัวอักษร ชื่อ}
{ตัวอักษร. Semalt เป็นวิธีที่เราสามารถนำมาใช้แก้ปัญหานี้ได้สามวิธี

วิธีการ setState

วิธีที่ง่ายที่สุดในการทำ React นี้คือใช้ setState เพื่อเก็บข้อมูลภายในคอมโพเนนต์เอง

     // รหัสอักขระ GoTCharacter jsชั้นการส่งออก StatefulCharacterRow ขยาย Component {constructor    {ซุปเปอร์   ;นี้. state = {show_description: เท็จ}}render    {const {character} = นี้ อุปกรณ์ประกอบฉาก;return ( 
{ตัวอักษร ชื่อ}
=> นี้ setState ({show_description:! นี้ สถานะ - commercial real estate valuation report. show_description})}>{นี้. สถานะ. show_description? 'ยุบ': 'ขยาย'}{นี้. สถานะ. show_description &&
{ตัวอักษร description}
}
);}};

วิธี Redux

การใช้ setState จะใช้งานได้ตราบเท่าที่รัฐที่เรากำลังติดต่ออยู่มีเฉพาะเฉพาะส่วนประกอบเท่านั้น ตัวอย่างเช่นถ้าเราต้องการวางตำแหน่งเป็น "ขยายทั้งหมด" ฟังก์ชันจะเป็นการยากที่จะจัดการกับ React เพียงแค่นี้

ลองดูวิธีที่เราสามารถย้ายไป Redux:

     // FlickDuck js// .ส่งออก const toggleCharacterDescription = createAction (FlixActions TOGGLE_CHARACTER_DESCRIPTION, (character) => ({character}));การส่งออกเริ่มต้น (current_state, action) => {const state = current_state || default_state;เปลี่ยน (ประเภทการกระทำ) {กรณี FlixActions TOGGLE_CHARACTER_DESCRIPTION:return { รัฐ, ตัวอักษร: รัฐ ตัวละคร แผนที่ (char => {ถ้า (char. id === การกระทำ payload ตัวอักษร id) {return { char, show_description:! char show_description};}กลับถ่าน;})}ค่าเริ่มต้น:รัฐกลับ}}    
     // GoTCharactersContainer. jsนำเข้า {connect} จาก 'react-redux';นำเข้า GoTCharacters จาก '. / GoTCharacters';นำเข้า {toggleCharacterDescription} จาก '. / FlickDuck ';const mapStateToProps = (state) => ({.รัฐสะบัด});const mapDispatchToProps = (ส่ง) => ({toggleCharacterDescription: (data) => dispatch (toggleCharacterDescription (data))});การส่งออกเริ่มต้นเชื่อมต่อ (mapStateToProps, mapDispatchToProps) (GoTCharacters);    
     // อักขระอักขระ GoT jsconst GoTCharacters = ({characters, toggleCharacterDescription}) => {กลับ ( 
{ตัวอักษร แผนที่ (char => ( ))}
);};การส่งออก const CharacterRow = ({character, toggleCharacterDescription}) => (
{ตัวอักษร ชื่อ}
{ตัวอักษร show_description? 'ยุบ': 'ขยาย'}{ตัวอักษร show_description &&
{ตัวอักษร description}
}
);

Semalt จัดเก็บสถานะของฟิลด์คำอธิบายภายในออบเจกต์อักขระ รัฐของเราจะมีลักษณะดังนี้:

     state = {อักขระ: [{id: 1,ชื่อ: "Eddard Ned Stark",บ้าน: "สิ้นเชิง",คำอธิบาย: "Lord of Winterfell - ผู้พิทักษ์แห่งภาคเหนือ - พระหัตถ์ของกษัตริย์ - แต่งงานกับ Catelyn (Tully) Stark"imageSuffix: "eddard-stark",wikiSuffix: "Eddard_Stark",show_description: จริง}{id: 2,ชื่อ: "Benjen Stark",บ้าน: "สิ้นเชิง",คำอธิบาย: "บราเดอร์แห่ง Eddard Stark - แรนเจอร์แรกของ Night's Watch"imageSuffix: "benjen-stark",wikiSuffix: "Benjen_Stark",show_description: เท็จ}]}    

นี่เป็นรูปแบบทั่วไปที่นักพัฒนาซอฟต์แวร์จำนวนมากปฏิบัติตามเมื่อพวกเขากำลังเริ่มต้นกับ Redux.

จนถึงตอนนี้เราได้รับมือกับตัวละครจากบทแรกของ GoT และจักรวาลกำลังจะมีขนาดใหญ่ขึ้น เมื่อใดก็ตามที่แอปของเราจะทำงานช้า Semalt looping ผ่าน 1000 อักขระเพื่ออัพเดตหนึ่งแถว

Semalt ดูวิธีการปรับขนาดสำหรับชุดข้อมูลขนาดใหญ่:

     // FlickDuck js// .กรณี FlixActions TOGGLE_CHARACTER_DESCRIPTION:const {character} = action น้ำหนักบรรทุก;return { สถานะ,character_show_description: { สถานะ. character_show_description,[ตัวละคร id]: รัฐ! character_show_description [ตัวละคร ID]}}// .    

และใน อักขระ GoT js :

     การส่งออก const CharacterRow = ({character, character_show_description, toggleCharacterDescription}) => ( 
{ตัวอักษร ชื่อ}
{character_show_description [ตัวละคร id]? 'ยุบ': 'ขยาย'}{character_show_description [ตัวละคร id] &&
{ตัวอักษร description}
}
);

เมื่อผู้ใช้คลิกที่ลิงค์ ขยาย เราจะอัพเดต character_show_description ด้วยรหัสตัวอักษรปัจจุบัน รัฐดูเหมือนว่าตอนนี้:

     state = {อักขระ: [ ]character_show_description: {1: จริง,2: เท็จ}}    

ตอนนี้เราสามารถอัพเดตสถานะ UI ได้โดยไม่ต้องวนรอบตัวอักษรทั้งหมด

การจัดการสถานะของแบบฟอร์มใน Redux

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

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

ลองดูวิธีที่เราสามารถใช้กับ Redux ได้

     // FlickDuck js// ============const FlixActions = km ({FETCH_CHARACTERS: null,TOGGLE_CHARACTER_DESCRIPTION: null,TOGGLE_CHARACTER_EDIT: null,SYNC_CHARACTER_EDIT_DATA: null,SAVE_CHARACTER_EDIT: null});const default_state = {อักขระ: อักขระ,character_show_description: {},show_character_edit: {},character_edit_form_data: {}};ส่งออก const toggleEdit = createAction (FlixActions TOGGLE_CHARACTER_EDIT, (character) => ({character}));export const syncCharacterEditData = createAction (FlixActions SYNC_CHARACTER_EDIT_DATA, (character, form_data) => ({character, form_data}));การส่งออก const editCharacterDetails = createAction (FlixActions SAVE_CHARACTER_EDIT, (character) => ({character}));การส่งออกเริ่มต้น (current_state, action) => {// .เปลี่ยน (ประเภทการกระทำ) {// .กรณี FlixActions TOGGLE_CHARACTER_EDIT:อักขระ = การกระทำ น้ำหนักบรรทุก ตัวละคร;const show_character_edit =! state show_character_edit [ตัวละคร ID];return { สถานะ,show_character_edit: { สถานะ. show_character_edit,[ตัวละคร id]: show_character_edit}, character_edit_form_data: { สถานะ. character_edit_form_data,[ตัวละคร id]: show_character_edit? { . อักขระ}: {}}}กรณี FlixActions SYNC_CHARACTER_EDIT_DATA:อักขระ = การกระทำ น้ำหนักบรรทุก ตัวละคร;const {form_data} = action น้ำหนักบรรทุก;return { สถานะ,character_edit_form_data: { สถานะ. character_edit_form_data,[ตัวละคร id]: { form_data}}}กรณี FlixActions. น้ำหนักบรรทุก ตัวละคร;const edit_form_data = สถานะ character_edit_form_data [ตัวละคร ID];const characters = state ตัวละคร แผนที่ (char => {ถ้า (char. id === อักขระ. id) return { ชื่อ: edit_form_data ชื่อ, รายละเอียด: edit_form_data คำอธิบาย}กลับถ่าน;});return { สถานะ,ตัวอักษรshow_character_edit: { สถานะ. show_character_edit,[ตัวละคร id]: false}}// .}}    
     // GotCharacters. jsการส่งออก const CharacterRow = ({character, character_show_description, character_edit_form_data, show_character_edit, toggleCharacterDescription, toggleEdit, syncCharacterEditData, editCharacterDetails}) => {const toggleEditPartial = toggleEdit. ผูก (null, อักขระ);return ( 
{ตัวอักษร ชื่อ}
{character_show_description [ตัวละคร id]? 'ยุบ': 'ขยาย'}{! character_show_description [ตัวละคร id] && แก้ไข}{character_show_description [ตัวละคร id] &&
{ตัวอักษร description}
}{show_character_edit [ตัวละคร id] && }
);}การส่งออก const EditCharacterDetails = ({character, edit_data, syncCharacterEditData, editCharacterDetails, cancelEdit}) => {const syncFormData = (คีย์, e) => {const {value} = e currentTarget;syncCharacterEditData (อักขระ {.edit_data,[key]: ค่า});};const saveForm = (e) => {อี ป้องกันไม่ให้ ;editCharacterDetails (ตัวอักษร);};กลับ (
March 1, 2018