การสร้างไลบรารีการตรวจสอบ React ของคุณเอง: ประสบการณ์นักพัฒนา (ตอนที่ 3)
เผยแพร่แล้ว: 2022-03-10หากคุณได้ติดตามชุดบทความเล็กๆ นี้ ตอนนี้คุณได้เรียนรู้วิธีรวบรวมไลบรารีการตรวจสอบความถูกต้องของคุณเองแล้ว มันสามารถจัดการกับความท้าทายเกือบทุกอย่างที่คุณทำได้ และยังช่วยในเรื่องการเข้าถึงอีกด้วย! ความหายนะเพียงอย่างเดียวของมันคือมันแย่มากที่จะทำงานด้วย
ใช่ถูกต้อง ประสบการณ์ผู้ใช้จากมุมมองของนักพัฒนาขาดไปอย่างมาก เราไม่ได้รับคำเตือนที่เป็นประโยชน์ใดๆ เมื่อเราสะกดคำผิด ใช้ API ในทางที่ผิด หรืออะไรก็ตาม จริงๆ แล้ว!
บทความนี้จะแนะนำคุณเกี่ยวกับวิธีการปรับปรุงประสบการณ์นักพัฒนาซอฟต์แวร์ของไลบรารีการตรวจสอบของคุณ — หรือไลบรารีใดๆ เพื่อประโยชน์นั้น
- ตอนที่ 1: พื้นฐาน
- ส่วนที่ 2: คุณสมบัติ
- ตอนที่ 3: ประสบการณ์
การเริ่มต้น
ตั้งแต่ส่วนสุดท้ายของบทความนี้ เราได้ดึงโค้ดไลบรารีทั้งหมดออกมาเป็นไฟล์ของตัวเอง ดูการสาธิต CodeSandbox เพื่อดูว่าเรากำลังเริ่มต้นอะไร
ฟังก์ชั่นอำนวยความสะดวก
เราต้องการให้ห้องสมุดของเราใช้งานง่ายที่สุดสำหรับกรณีทั่วไปส่วนใหญ่ วิธีที่จะก้าวไปสู่เป้าหมายนั้นคือการเพิ่มฟังก์ชันยูทิลิตี้ที่สะดวกสำหรับฟังก์ชันบางอย่าง
คุณลักษณะหนึ่งดังกล่าวอาจเป็นการตรวจสอบว่าแบบฟอร์มของเราถูกต้องหรือไม่ กล่าวคือ หากข้อความแสดงข้อผิดพลาดทั้งหมดเป็น null
นี่คือสิ่งที่คุณมักจะตรวจสอบในตัวจัดการ onSubmit
ของคุณ แต่ก็อาจมีประโยชน์ในวิธีการเรนเดอร์ของคุณด้วย มาดำเนินการกันเถอะ!
const isFormValid = useMemo( () => Object.values(errors).every(error => error === null), [errors] );
เราจะระบุแฟล็กนี้ในตัวจัดการแบบฟอร์ม onSubmit
ของเรา เช่นเดียวกับในวิธีการเรนเดอร์ของเรา
- ดูการสาธิต CodeSandbox
มีอีกมากมายที่สามารถเขียนได้ แต่ฉันจะปล่อยให้เป็นแบบฝึกหัดสำหรับผู้อ่าน
คำเตือนการพัฒนาและค่าคงที่
หนึ่งในคุณสมบัติที่ยอดเยี่ยมที่สุดของ React คือคำเตือนคอนโซลที่มีประโยชน์มากมายในขณะพัฒนา เราควรให้คุณภาพประเภทเดียวกันแก่ผู้ใช้ของเราเช่นกัน
ในการเริ่มต้น เราจะสร้างสองฟังก์ชัน — warning
สำหรับการบันทึกคำเตือนไปยังคอนโซล และ invariant
ที่สำหรับการโยนข้อผิดพลาด — ทั้ง 2 อย่างหากไม่ตรงตามเงื่อนไขที่กำหนด
function warning(condition, message) { if (process.env.NODE_ENV === 'production' || condition) { return; } console.warn('useValidation: ' + message); } function invariant(condition, message) { if (process.env.NODE_ENV === 'production' || condition) { return; } throw new Error('useValidation: ' + message); }
คุณต้องการใช้ invariant
ที่หากข้อผิดพลาดจะทำให้ไลบรารีของคุณขัดข้อง (หรือทำให้ไม่มีประโยชน์) และ warning
สำหรับแนวทางปฏิบัติที่ไม่ดีหรือคำแนะนำอื่นๆ
เมื่อจะเตือน
การตัดสินใจว่าจะเตือนเมื่อใดจึงสำคัญมาก มากเกินไปและคุณก็น่ารำคาญ มีน้อยเกินไปและคุณปล่อยให้ข้อบกพร่องที่สำคัญถูกส่งไปยังการผลิต ดังนั้น เราจึงต้องฉลาดในการตักเตือน
เนื่องจากไลบรารีของเรายอมรับอ็อบเจ็กต์การกำหนดค่าที่ค่อนข้างใหญ่ จึงควรตรวจสอบสิ่งนี้ อย่างน้อยก็ในขณะพัฒนา เราสามารถแก้ไขได้โดยใช้ระบบประเภทเช่น TypeScript หรือ Flow แต่ไม่รวมผู้ใช้ JavaScript รุ่นเก่าทั้งหมด
ให้สร้างตัวตรวจสอบสคีมารันไทม์แทน ซึ่งเราตรวจสอบว่าการกำหนดค่าประกอบด้วยฟิลด์ที่ถูกต้อง และพิมพ์คำเตือนที่เกี่ยวข้อง
function validateConfigSchema(config) { if (process.env.NODE_ENV === 'production') { return; } if (typeof config === 'function') { config = config({}); } invariant( typeof config === 'object', `useValidation should be called with an object or a function returning an object. You passed a ${typeof config}.`, ); invariant( typeof config.fields === 'object', 'useValidation requires a `field` prop with an object containing the fields and their validators. Please refer to the documentation on usage: https://link.to/docs' ); invariant( Object.values(config.fields).every(field => typeof field === 'object'), 'useValidation requires that the `field` object only contains objects. It looks like yours isn\'t. Please refer to the documentation on usage: https://link.to/docs' ); warning( ['always', 'blur', 'submit', undefined].includes(config.showError), 'useValidation received an unsupported value in the `showError` prop. Valid values are "always", "blur" or "submit".' ) // And so on }
เราอาจจะทำสิ่งนี้ต่อไปได้ซักพักถ้าเราต้องการใช้เวลา และคุณควร! เป็นวิธีที่ยอดเยี่ยมในการปรับปรุงประสบการณ์ของนักพัฒนาแอปของคุณ
คุณไม่จำเป็นต้องเขียนสิ่งเหล่านี้ด้วยมือ มีพอร์ตเบราว์เซอร์ของ joi
ไลบรารีตรวจสอบความถูกต้องของอ็อบเจ็กต์ที่เป็นที่นิยมซึ่งสามารถช่วยสร้างการตรวจสอบการตรวจสอบรันไทม์ที่ดีจริงๆ นอกจากนี้ ตามที่กล่าวไว้ก่อนหน้านี้ ระบบประเภทจะช่วยตรวจจับข้อผิดพลาดของการกำหนดค่า ณ เวลารวบรวมสำหรับผู้ใช้ที่ใช้ระบบประเภทนั้น
อนุญาตให้มีความยืดหยุ่น
ประสบการณ์ของนักพัฒนาที่ดีนั้นส่วนใหญ่จะไม่ขัดขวางนักพัฒนา มาดูวิธีที่เราสามารถปรับปรุงประสบการณ์ดังกล่าวได้สองสามวิธี
เขียนอุปกรณ์ประกอบฉากที่ขัดแย้งกัน
ประการแรก ผู้จัดหาอุปกรณ์ประกอบฉากของเราใช้อุปกรณ์ประกอบฉากบางอย่างกับข้อมูลป้อนเข้าและแบบฟอร์มที่ผู้บริโภคสามารถลบล้างได้โดยไม่ได้ตั้งใจ ให้เพิ่มอ็อบเจ็กต์แทนที่ prop ให้กับ prop getter ของเรา ซึ่งจะประกอบ props ที่ขัดแย้งกันเข้าด้วยกัน
นี่คือวิธีที่เราสามารถนำไปใช้ใน getFieldProps
ของเรา:
getFieldProps: (fieldName, overrides = {}) => ({ onChange: e => { const { value } = e.target; if (!config.fields[fieldName]) { return; } dispatch({ type: 'change', payload: { [fieldName]: value }, }); if (overrides.onChange) { overrides.onChange(e); } }, onBlur: e => { dispatch({ type: 'blur', payload: fieldName }); if (overrides.onBlur) { overrides.onBlur(e) } }, name: overrides.name || fieldName, value: state.values[fieldName] || '', }),
วิธีการที่คล้ายกันสามารถติดตามได้ใน getFormProps
ช่วยหลีกเลี่ยงการเจาะเสา
บางรูปแบบอาจมีขนาดใหญ่และแบ่งออกเป็นหลายส่วน แทนที่จะทำให้ผู้บริโภคของเราเจาะอุปกรณ์ลงต้นไม้ เราควรให้บริบท ด้วยวิธีนี้ พวกเขาสามารถเข้าถึงสิ่งของทั้งหมดที่เราส่งคืนจาก hook แบบกำหนดเองของเราได้ทุกที่ในแผนผังด้านล่าง
ขั้นแรก ให้สร้าง ValidationContext ด้วยเมธอด createContext
ของ React:
export const ValidationContext = React.createContext({});
ต่อไป มาสร้างองค์ประกอบ ValidationProvider
ที่ให้ค่าทั้งหมดจากเบ็ด useValidation
ในบริบทแทน:
export const ValidationProvider = props => { const context = useValidation(props.config); return ( {props.children} ); };
export const ValidationProvider = props => { const context = useValidation(props.config); return ( {props.children} ); };
export const ValidationProvider = props => { const context = useValidation(props.config); return ( {props.children} ); };
ตอนนี้ แทนที่จะเรียก useValidation
โดยตรง เราจะรวมแบบฟอร์มของเราไว้ในองค์ประกอบ ValidationProvider
และเข้าถึงอุปกรณ์ตรวจสอบความถูกต้อง ( getFormProps
errors
ฯลฯ ) โดยใช้เบ็ด useContext
คุณจะใช้มันแบบนี้:
Import React, { useContext } from 'react'; import { ValidationContext } from './useValidation'; function UsernameForm(props) { const { getFieldProps, errors } = useContext(ValidationContext); return ( <> <input {...getFieldProps('username')} /> {errors.username && {errors.username}></span>} </> ); }
ด้วยวิธีนี้คุณจะได้รับสิ่งที่ดีที่สุดจากทั้งสองโลก! คุณได้รับเบ็ดง่ายๆ สำหรับสถานการณ์ง่ายๆ เหล่านั้น และคุณจะได้รับความยืดหยุ่นที่คุณต้องการสำหรับชิ้นส่วนที่ซับซ้อนเหล่านั้น
เอกสารสำคัญ
เมื่อใดก็ตามที่ฉันใช้ห้องสมุด ฉันไม่ได้เขียนเอง ฉันชอบเอกสารที่ดี แต่คุณควรเน้นที่อะไร และคุณควรจัดทำเอกสารที่ไหน
ขั้นตอนแรกควรรวบรวม README ที่เข้าใจง่าย พร้อมตัวอย่างการใช้งานพื้นฐานที่พร้อมใช้งาน Andrew Healey เขียนบทความที่น่าทึ่งเกี่ยวกับวิธีการเขียน README ที่ดี ซึ่งผมขอแนะนำให้คุณอ่าน
เมื่อคุณสร้าง README ที่ดีเพื่อจูงใจผู้คน เว็บไซต์เอกสารอาจเป็นความคิดที่ดี ที่นี่ คุณสามารถใส่เอกสาร API เชิงลึก สูตรสำหรับกรณีการใช้งานทั่วไป และคำถามที่พบบ่อยที่ดี
มีเครื่องมือที่ยอดเยี่ยมสำหรับสร้างเว็บไซต์เอกสาร สิ่งที่ฉันชอบคือ docusaurus
จาก Facebook (โม้น้อยใจ: เราใช้มันเมื่อสร้างเว็บไซต์ create-react-app
) แต่มีทางเลือกที่ดีหลายประการ
เราจะไม่พูดถึงวิธีการเขียนเอกสารที่ดีในบทความนี้ มีบทความดีๆ มากมาย แม้แต่ชุมชนที่เรียกว่า "Write the Docs" พวกเขาได้เขียนคำแนะนำที่ดีเกี่ยวกับวิธีเริ่มต้นเขียนเอกสารที่ยอดเยี่ยม
สรุป
ในชุดบทความนี้ เราได้สร้างไลบรารีการตรวจสอบที่ดีพอสมควร มันมี API ที่ค่อนข้างเรียบง่าย มีความยืดหยุ่นเมื่อคุณต้องการ ประสบการณ์ของนักพัฒนาที่ดีและคุณสมบัติที่แย่มาก
เราได้ศึกษาวิธีที่เราใช้สิ่งต่าง ๆ ทีละขั้นตอน และฉันหวังว่าคุณจะเข้าใจอย่างลึกซึ้งถึงวิธีการสร้างห้องสมุดของคุณเอง และวิธีสร้างห้องสมุดที่ผู้คนชอบที่จะใช้
โปรดแจ้งให้เราทราบในความคิดเห็นว่าคุณคิดอย่างไร และหากมีบางส่วนที่คุณติดอยู่หรือมีปัญหาในการทำความเข้าใจ ฉันจะพยายามอย่างเต็มที่เพื่ออัปเดตบทความเมื่อมีความคิดเห็นเข้ามา
หากต้องการปิดบทความนี้ — นี่คือเวอร์ชันสุดท้าย:
- ดูการสาธิต CodeSandbox
ขอบคุณที่อ่าน!