ห่อส่วนประกอบปฏิกิริยาที่ควบคุมเพื่ออนุญาตให้คู่ Prop/Handler ที่เฉพาะเจาะจงถูกละไว้โดยผู้บริโภคส่วนประกอบ ไม่สามารถควบคุมได้ช่วยให้คุณสามารถเขียนส่วนประกอบที่ตอบสนองได้โดยมีสถานะน้อยที่สุดแล้วห่อไว้ในองค์ประกอบที่จะจัดการสถานะสำหรับเสา/ตัวจัดการหากพวกเขาถูกแยกออก
npm i -S uncontrollable
หากคุณไม่แน่ใจว่า ทำไม โมดูลนี้อ่านส่วนถัดไปก่อน หากคุณเพียงแค่ต้องการดูตัวอย่างในโลกแห่งความจริงลองดูวิดเจ็ต React ซึ่งใช้กลยุทธ์นี้อย่างหนัก
import { uncontrollable } from 'uncontrollable' ;
useUncontrolledProp(value, defaultValue, onChange) => [value, onChange]
เบ็ดตอบสนองที่สามารถใช้แทนส่วนประกอบลำดับที่สูงกว่าข้างต้น มันส่งคืนชุด props
ที่สมบูรณ์ซึ่งปลอดภัยในการแพร่กระจายไปยังองค์ประกอบเด็ก
import { useUncontrolledProp } from 'uncontrollable' ;
const UncontrolledCombobox = ( { value , defaultValue , onChange } ) => {
// filters out defaultValue, defaultOpen and returns controlled
// versions of onChange, and onToggle.
const [ controlledValue , onControlledChange ] = useUncontrolledProp (
value ,
defaultValue ,
onChange
) ;
return < Checkbox { ... controlledProps } / > ;
} ;
useUncontrolled(props, propsHandlerHash) => controlledProps
เบ็ดตอบสนองที่สามารถใช้แทนส่วนประกอบลำดับที่สูงกว่าข้างต้น มันส่งคืนชุด props
ที่สมบูรณ์ซึ่งปลอดภัยในการแพร่กระจายไปยังองค์ประกอบเด็ก
import { useUncontrolled } from 'uncontrollable' ;
const UncontrolledCombobox = ( props ) => {
// filters out defaultValue, defaultOpen and returns controlled
// versions of onChange, and onToggle.
const controlledProps = useUncontrolled ( props , {
value : 'onChange' ,
open : 'onToggle' ,
} ) ;
return < Checkbox { ... controlledProps } / > ;
} ;
หนึ่งในจุดแข็งของการตอบสนองคือแบบจำลองการยืดตัวซึ่งเปิดใช้งานโดยการปฏิบัติทั่วไปของการผลักสถานะส่วนประกอบให้สูงขึ้นต้นไม้มากที่สุด ในขณะที่ยอดเยี่ยมสำหรับการเปิดใช้งานเหตุผลที่ยืดหยุ่นและง่ายต่อการใช้งานส่วนประกอบสิ่งนี้สามารถสร้างแผ่นหม้อไอน้ำจำนวนมากให้กับส่วนประกอบลวดกับการใช้งานทุกครั้ง สำหรับส่วนประกอบที่ง่าย (เช่นอินพุต) นี่เป็นเรื่องของการผูก value
อินพุต prop prop ไปยังคุณสมบัติสถานะหลักผ่านตัวจัดการ onChange
นี่คือรูปแบบที่พบบ่อยมาก:
render ( ) {
return (
< input type = 'text'
value = { this . state . value }
onChange = { e => this . setState ( { value : e . target . value } ) }
/ >
)
}
รูปแบบนี้ย้ายความรับผิดชอบของการจัดการ value
จากอินพุตไปยังผู้ปกครองและเลียนแบบ "สองทาง" ดาต้าดิง อย่างไรก็ตามบางครั้งไม่จำเป็นต้องให้ผู้ปกครองจัดการสถานะของอินพุตโดยตรง ในกรณีนั้นสิ่งที่เราต้องการทำคือตั้ง value
เริ่มต้นของอินพุตและปล่อยให้อินพุตจัดการตั้งแต่นั้นมา ทำปฏิกิริยากับสิ่งนี้ผ่านอินพุต "ไม่สามารถควบคุมได้" ซึ่งหากคุณไม่ได้ระบุว่าคุณต้องการควบคุมสถานะของอินพุตจากภายนอกผ่านเสา value
มันจะทำหนังสือสำหรับคุณ
นี่เป็นรูปแบบที่ยอดเยี่ยมที่เราสามารถใช้ในส่วนประกอบของเราเอง มักจะเป็นการดีที่สุดที่จะสร้างแต่ละองค์ประกอบให้ไร้สัญชาติที่สุดเท่าที่จะเป็นไปได้โดยสมมติว่าผู้ปกครองจะต้องการควบคุมทุกสิ่งที่สมเหตุสมผล ใช้ส่วนประกอบแบบเลื่อนลงอย่างง่ายเป็นตัวอย่าง
class SimpleDropdown extends React . Component {
static propTypes = {
value : React . PropTypes . string ,
onChange : React . PropTypes . func ,
open : React . PropTypes . bool ,
onToggle : React . PropTypes . func ,
} ;
render ( ) {
return (
< div >
< input
value = { this . props . value }
onChange = { ( e ) => this . props . onChange ( e . target . value ) }
/ >
< button onClick = { ( e ) => this . props . onToggle ( ! this . props . open ) } >
open
< / button >
{ this . props . open && (
< ul className = "open" >
< li > option 1 < / li >
< li > option 2 < / li >
< / ul >
) }
< / div >
) ;
}
}
สังเกตว่าเราไม่ติดตามสถานะใด ๆ ในการเลื่อนลงอย่างง่าย ๆ ของเราได้อย่างไร? นี่เป็นสิ่งที่ยอดเยี่ยมเพราะผู้บริโภคโมดูลของเราจะมีความยืดหยุ่นทั้งหมดในการตัดสินใจว่าพฤติกรรมของการเลื่อนลงควรเป็นอย่างไร นอกจากนี้ยังสังเกตเห็น API สาธารณะของเรา (Proptypes) ประกอบด้วยรูปแบบทั่วไป: คุณสมบัติที่เราต้องการตั้งค่า ( value
open
) และชุดของตัวจัดการที่ระบุ เมื่อ เราต้องการตั้งค่า ( onChange
, onToggle
) มันขึ้นอยู่กับองค์ประกอบหลักในการเปลี่ยน value
และ open
อุปกรณ์ประกอบฉากเพื่อตอบสนองต่อตัวจัดการ
ในขณะที่รูปแบบนี้มีความยืดหยุ่นในปริมาณที่ดีเยี่ยมสำหรับผู้บริโภค แต่ก็ต้องการให้พวกเขาเขียนโค้ดแผ่นหม้อต้มหลาย ๆ อันซึ่งอาจไม่เปลี่ยนจากการใช้งานมากนัก ในทุกโอกาสพวกเขามักจะต้องการ open
เพื่อตอบสนองต่อ onToggle
และในบางกรณีที่หายากเท่านั้นที่ต้องการแทนที่พฤติกรรมนั้น นี่คือที่ซึ่งรูปแบบการควบคุม/ควบคุมไม่ได้เข้ามา
เราต้องการจัดการกรณีเปิด/ontoggle ด้วยตัวเองหากผู้บริโภคไม่ได้ให้เสา open
(ระบุว่าพวกเขาต้องการควบคุมมัน) แทนที่จะทำให้ส่วนประกอบแบบเลื่อนลงของเราซับซ้อนขึ้นด้วยตรรกะทั้งหมดที่บดบังตรรกะทางธุรกิจของดรอปดาวน์ของเราเราสามารถเพิ่มได้ในภายหลังโดยใช้ดรอปดาวน์ของเราและห่อมันไว้ในองค์ประกอบอื่นที่จัดการกับเรา
uncontrollable
ช่วยให้คุณแยกตรรกะที่จำเป็นในการสร้างอินพุตที่ควบคุม/ไม่สามารถควบคุมได้ช่วยให้คุณมุ่งเน้นไปที่การสร้างอินพุตที่ควบคุมอย่างสมบูรณ์และห่อหุ้มในภายหลัง สิ่งนี้มีแนวโน้มที่จะง่ายกว่าที่จะให้เหตุผลเช่นกัน
import { uncontrollable } from 'uncontrollable' ;
const UncontrollableDropdown = uncontrollable ( SimpleDropdown , {
value : 'onChange' ,
open : 'onToggle'
} )
< UncontrollableDropdown
value = { this . state . val } // we can still control these props if we want
onChange = { val => this . setState ( { val } ) }
defaultOpen = { true } / > // or just let the UncontrollableDropdown handle it
// and we just set an initial value (or leave it out completely)!
ตอนนี้เราไม่จำเป็นต้องกังวลเกี่ยวกับ Ontoggle ที่เปิดอยู่! ส่วนประกอบที่ส่งคืนจะ open
ให้เราโดยสมมติว่าควรเปิดให้ open
เป็นสิ่งที่ onToggle
ส่งคืน หากเรา ต้องการ กังวลเกี่ยวกับเรื่องนี้เราสามารถจัดเตรียมอุปกรณ์ประกอบฉาก open
และ onToggle
และอินพุตที่ไม่สามารถควบคุมได้จะผ่านพวกเขาผ่าน
ข้างต้นเป็นตัวอย่างที่วางแผนไว้ แต่ช่วยให้คุณสามารถห่อส่วนประกอบที่ซับซ้อนยิ่งขึ้นให้ความยืดหยุ่นใน API มากคุณสามารถเสนอผู้บริโภคส่วนประกอบของคุณ สำหรับทุกคู่ของ prop/handlers คุณจะได้รับ defaultprop ของแบบฟอร์ม "ค่าเริ่มต้น [propname]" ดังนั้น value
-> defaultValue
และ open
-> defaultOpen
ฯลฯ วิดเจ็ต React ใช้ประโยชน์จากกลยุทธ์นี้อย่างหนัก ที่นี่: https://github.com/jquense/react-widgets/blob/5d1b530cb094cdc72f577fe01abe4a02dd265400/src/multiselect.jsx#l521