เมื่อเร็วๆ นี้ ฉันเริ่มใช้ React และ Redux เพื่อสร้างหนึ่งในองค์ประกอบหลักบนเว็บไซต์ Gogobot

เพื่อให้เข้าใจปัญหาได้ดีขึ้น ต่อไปนี้เป็นภาพหน้าจอของส่วนประกอบใดส่วนประกอบหนึ่งในหน้านั้น

หากไม่เข้าใจรายละเอียดขององค์ประกอบจริงๆ คุณจะเห็นว่าส่วนประกอบต่างๆ มีหลายสิ่งหลายอย่างร่วมกัน:

  1. นับป้ายกำกับที่แสดง/ซ่อนตามจำนวนรายการที่ฉันเลือกจากตัวกรอง
  2. ดรอปดาวน์ที่เปิดขึ้นเมื่อคลิกที่ไอคอน
  3. เมื่อคลิกแล้ว จะส่งเหตุการณ์ (การกระทำ) และขอข้อมูลจาก
  4. เมื่อคลิกแล้ว ระบบจะส่งเหตุการณ์ (การกระทำ) และขอข้อมูลจากเซิร์ฟเวอร์ตามตัวกรองใหม่

เมื่อนั่งลงเพื่อออกแบบส่วนประกอบนี้ ฉันพบว่า **พฤติกรรม** ที่ใช้ร่วมกันระหว่างแต่ละองค์ประกอบนั้นจำเป็นต้องมี **ส่วนประกอบลำดับที่สูงกว่า** ที่จะกำหนดพฤติกรรมและรวมส่วนประกอบ "รอง" ทั้งหมด

การทำสิ่งนี้ด้วย Pure React นั้นค่อนข้างชัดเจน ดังนั้นฉันจะไม่พูดถึงสิ่งนั้น โพสต์นี้จะเกี่ยวกับการทำเช่นนี้ด้วย Redux เนื่องจากองค์ประกอบที่มีลำดับสูงกว่านั้นเชื่อมต่อกับการจัดส่ง การจัดเก็บ และสถานะ

การนำไปปฏิบัติ

// src/components/Filters/FilterWrapper/index.js
import React, { Component } from ‘react’;
import { bindActionCreators } from ‘redux’;
import { connect } from ‘react-redux’;
function FilterWrapper(ComposedFilter, filterInfo) {
 class BaseFilter extends Component {
 constructor() {
 super();
 this.state = {
 count: 0
 };
 this.onCheckboxChange = this.onCheckboxChange.bind(this);
 }
onClick(e) {
 
 }
onCheckboxChange(e) {
 
 }
render() {
 let countLabel = this.state.count > 0 ?
 <span>{ this.state.count }</span> :
 null;
return(
 <div className=”filterDetailsWrapper”>
 <div className=”filterTotalCount”>
 { countLabel }
 </div>
 <div className=”optionsDropDownContainer”>
 <ComposedFilter
 {…this.state}
 {…this.props}
 onCheckboxChange={ this.onCheckboxChange }
 />
 </div>
 </div>
 );
 }
 }
function mapStateToProps(state) {
 // REDACTED
 return {};
 }
function mapDispatchToProps(dispatch) {
 return {
 …bindActionCreators(actions, dispatch)
 };
 }
 return connect(mapStateToProps, mapDispatchToProps)(BaseFilter);
}
export default FilterWrapper;

ให้อธิบายสิ่งที่เกิดขึ้นที่นี่...

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

มาดูส่วนประกอบที่ห่อไว้ (HotelClass) สำหรับตัวอย่างนี้

// src/components/Filters/HotelClass/index.js
import React, { Component } from ‘react’;
import ReactDOM from ‘react-dom’;
import BaseFilterWrapper from ‘../BaseFilterWrapper’;
class HotelClass extends Component {
 render() {
 return(
 <div className=”hotelClassOptions”>
 <ul>
 <li className=”optionsdropdown”>
 <label className=”optionTitle”>5</label>
 <input onChange={ this.props.onCheckboxChange } type=”checkbox” value=”5" />
 </li>
 <li className=”optionsdropdown”>
 <label className=”optionTitle”>4</label>
 <input onChange={ this.props.onCheckboxChange } type=”checkbox” value=”4" />
 </li>
 </ul>
 </div>
 )
 }
}
let filterInfo = {
 name: ‘hotel_class’,
 class_name: ‘hotelClass’,
 title: ‘Hotel Class’
};
export default BaseFilterWrapper(HotelClass, filterInfo);

อย่างที่คุณเห็น เมื่อช่องทำเครื่องหมายเปลี่ยนแปลง มันจะเรียก this.props.onCheckboxChange ซึ่งมาจากองค์ประกอบลำดับที่สูงกว่า และในทางกลับกันจะเรียกพฤติกรรมนั้นที่นั่น

บรรทัดสุดท้ายคือบรรทัดที่ “มหัศจรรย์” ฉันส่ง `filterInfo` บางส่วนซึ่งคุณสามารถใช้วิธีใดก็ได้ที่คุณเห็นว่าเหมาะสม (หรือไม่ก็ได้) และฉันส่งต่อองค์ประกอบ `HotelClass` ที่รวมอยู่ในฟังก์ชัน `BaseFilterWrapper`

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

onCheckboxChange(e) {
 let { count } = this.state;
 var { checked, value } = e.target;
 
 if (checked) {
 count += 1;
 } else {
 count -= 1;
 }
 
 this.setState({
 count
 });
}

เกี่ยวกับมัน.

ตอนนี้คุณสามารถแบ่งปันตรรกะของส่วนประกอบที่คล้ายกันได้แล้ว

ประโยชน์

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

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