การทำให้เป็นมาตรฐานอัตโนมัติและการอัปเดตข้อมูลสำหรับการดึงข้อมูลไลบรารี (react-query, swr, rtk-query และอื่น ๆ )
การแนะนำ
แรงจูงใจ
การติดตั้ง
เงื่อนไขที่จำเป็น
การทำให้อาร์เรย์เป็นมาตรฐาน
การดีบัก
ผลงาน
บูรณาการ
ตัวอย่าง
normy
เป็นไลบรารีที่ช่วยให้ข้อมูลแอปพลิเคชันของคุณถูกทำให้เป็นมาตรฐานโดยอัตโนมัติ จากนั้น เมื่อข้อมูลได้รับการทำให้เป็นมาตรฐานแล้ว ในหลายกรณี ข้อมูลของคุณจะได้รับการอัปเดตโดยอัตโนมัติ
แกนหลักของ normy
คือ @normy/core
Library ซึ่งไม่ได้มีไว้สำหรับใช้ในแอปพลิเคชันโดยตรง มีตรรกะอยู่ภายในซึ่งทำให้สามารถรวมเข้ากับไลบรารีดึงข้อมูลที่คุณชื่นชอบได้อย่างง่ายดาย มีการบูรณาการอย่างเป็นทางการกับ react-query
, swr
และ RTK Query
แล้ว หากคุณใช้ไลบรารีการดึงข้อมูลอื่น คุณสามารถแจ้งปัญหา Github ได้ ดังนั้นจึงอาจมีการเพิ่มเข้าไปด้วย
เพื่อให้เข้าใจว่าจริงๆ แล้ว normy
ทำอะไร วิธีที่ดีที่สุดคือดูตัวอย่าง สมมติว่าคุณใช้ react-query
จากนั้นคุณสามารถปรับโครงสร้างโค้ดใหม่ได้ด้วยวิธีต่อไปนี้:
นำเข้าปฏิกิริยาจาก 'ปฏิกิริยา'; นำเข้า { QueryClientProvider, แบบสอบถามลูกค้า ใช้แบบสอบถามลูกค้า, } จาก '@tanstack/react-query';+ นำเข้า { QueryNormalizerProvider } จาก '@normy/react-query'; const queryClient = QueryClient ใหม่ (); หนังสือ const = () => { const queryClient = useQueryClient(); const { data: booksData = [] } = useQuery(['books'], () => สัญญา แก้ไข ([ { id: '1', ชื่อ: 'ชื่อ 1', ผู้แต่ง: { id: '1001', ชื่อ: 'User1' } }, { id: '2' ชื่อ: 'ชื่อ 2' ผู้แต่ง: { id: '1002' ชื่อ: 'User2' } }, - - const { data: bookData } = useQuery(['book'], () => สัญญา แก้ไข ({ รหัส: '1', ชื่อ: 'ชื่อ 1', ผู้เขียน: { id: '1001', ชื่อ: 'User1' }, - - const updateBookNameMutation = useMutation({ การกลายพันธุ์Fn: () => ({ รหัส: '1', ชื่อ: 'ชื่อ 1 อัปเดต', }),- onSuccess:mutationData => {- queryClient.setQueryData(['books'], data =>- data.map(book =>- book.id === MutationData.id ? { ...book, . ..mutationData } : book,- ),- );- queryClient.setQueryData(['book'], data =>- data.id === MutationData.id ? { ...data, ...mutationData } : ข้อมูล,- );- - const updateBookAuthorMutation = useMutation({ การกลายพันธุ์Fn: () => ({ รหัส: '1', ผู้เขียน: { id: '1004', ชื่อ: 'User4' }, }),- onSuccess:mutationData => {- queryClient.setQueryData(['books'], data =>- data.map(book =>- book.id === MutationData.id ? { ...book, . ..mutationData } : book,- ),- );- queryClient.setQueryData(['book'], data =>- data.id === MutationData.id ? { ...data, ...mutationData } : ข้อมูล,- );- - const addBookMutation = useMutation({ การกลายพันธุ์Fn: () => ({ รหัส: '3', ชื่อ: 'ชื่อ 3', ผู้เขียน: { id: '1003', ชื่อ: 'User3' }, - // สำหรับข้อมูลที่มีอาร์เรย์ระดับบนสุด คุณยังต้องอัปเดตข้อมูลด้วยตนเอง onSuccess: การกลายพันธุ์ข้อมูล => { queryClient.setQueryData(['หนังสือ'], data => data.concat(mutationData)); - - // ส่งคืน JSX บางส่วน - แอป const = () => (+ <QueryNormalizerProvider queryClient={queryClient}> <QueryClientProvider client={queryClient}> <หนังสือ /> </QueryClientProvider>+ </QueryNormalizerProvider> -
อย่างที่คุณเห็น นอกเหนือจากอาร์เรย์ระดับบนสุดแล้ว ไม่จำเป็นต้องอัปเดตข้อมูลด้วยตนเองอีกต่อไป สิ่งนี้มีประโยชน์อย่างยิ่งหากการเปลี่ยนแปลงที่กำหนดควรอัปเดตข้อมูลสำหรับการสืบค้นหลายรายการ ไม่เพียงแต่เป็นการละเอียดในการอัปเดตด้วยตนเอง แต่คุณยังต้องรู้ด้วยว่าคำสั่งใดที่จะอัปเดต ยิ่งคุณมีคำถามมากเท่าไร normy
ก็จะได้เปรียบมากขึ้นเท่านั้น
มันทำงานอย่างไร? ตามค่าเริ่มต้น ออบเจ็กต์ทั้งหมดที่มีคีย์ id
จะถูกจัดระเบียบตามรหัส ตอนนี้ ออบเจ็กต์ใดๆ ที่มี id
คีย์จะถูกทำให้เป็นมาตรฐาน ซึ่งก็หมายถึงการจัดเก็บด้วยรหัส หากมีออบเจ็กต์ที่ตรงกันซึ่งมี id เดียวกันอยู่แล้ว ออบเจ็กต์ใหม่จะถูกรวมเข้ากับออบเจ็กต์ที่อยู่ในสถานะอยู่แล้ว ดังนั้น หากข้อมูลการตอบสนองของเซิร์ฟเวอร์จากการกลายพันธุ์คือ { id: '1', title: 'new title' }
ไลบรารีนี้จะคิดโดยอัตโนมัติเพื่ออัปเดต title
สำหรับออบเจ็กต์ที่มี id: '1'
สำหรับการสืบค้นที่เกี่ยวข้องทั้งหมด
นอกจากนี้ยังใช้งานได้กับวัตถุที่ซ้อนกันซึ่งมีรหัสไม่ว่าจะลึกแค่ไหนก็ตาม หากวัตถุที่มี id มีวัตถุอื่นที่มี id วัตถุเหล่านั้นจะถูกทำให้เป็นมาตรฐานแยกจากกัน และวัตถุหลักจะมีการอ้างอิงถึงวัตถุที่ซ้อนกันเหล่านั้นเท่านั้น
หากต้องการติดตั้งแพ็คเกจ เพียงเรียกใช้:
$ npm install @normy/react-query
หรือคุณสามารถใช้ CDN: https://unpkg.com/@normy/react-query
หากต้องการติดตั้งแพ็คเกจ เพียงเรียกใช้:
$ npm install @normy/swr
หรือคุณสามารถใช้ CDN: https://unpkg.com/@normy/swr
หากต้องการติดตั้งแพ็คเกจ เพียงเรียกใช้:
$ npm install @normy/rtk-query
หรือคุณสามารถใช้ CDN: https://unpkg.com/@normy/rtk-query
หากคุณต้องการเขียนปลั๊กอินไปยังไลบรารีอื่นนอกเหนือจาก react-query
, swr
หรือ rtk-query
:
$ npm install @normy/core
หรือคุณสามารถใช้ CDN: https://unpkg.com/@normy/core
หากต้องการดูวิธีเขียนปลั๊กอิน ตอนนี้เพียงตรวจสอบซอร์สโค้ดของ @normy/react-query
ซึ่งทำได้ง่ายมาก ในอนาคตคำแนะนำจะถูกสร้างขึ้น
เพื่อให้การทำงานเป็นมาตรฐานอัตโนมัติต้องเป็นไปตามเงื่อนไขต่อไปนี้:
คุณต้องมีวิธีที่เป็นมาตรฐานในการระบุอ็อบเจ็กต์ของคุณ โดยปกติแล้วจะทำได้โดยใช้ id
คีย์
รหัสต้องไม่ซ้ำกันทั่วทั้งแอป ไม่เพียงแต่ในประเภทออบเจ็กต์เท่านั้น หากไม่ คุณจะต้องเพิ่มบางอย่างต่อท้าย ซึ่งต้องทำเช่นเดียวกันในโลก GraphQL โดยปกติจะเพิ่ม _typename
ออบเจ็กต์ที่มีรหัสเดียวกันควรมีโครงสร้างที่สอดคล้องกัน หากออบเจ็กต์เช่นหนังสือในแบบสอบถามหนึ่งมีคีย์ title
ก็ควรจะเป็น title
ในผู้อื่น ไม่ใช่ name
อย่างกะทันหัน
มีฟังก์ชันที่สามารถส่งผ่านไปยัง createQueryNormalizer
เพื่อให้เป็นไปตามข้อกำหนดเหล่านั้นได้ กล่าวคือ getNormalizationObjectKey
getNormalizationObjectKey
สามารถช่วยคุณได้ในจุดที่ 1 ตัวอย่างเช่น หากคุณระบุออบเจ็กต์แตกต่างออกไป เช่น ด้วยคีย์ _id
คุณสามารถส่งผ่าน getNormalizationObjectKey: obj => obj._id
ได้
getNormalizationObjectKey
ยังช่วยให้คุณผ่านข้อกำหนดที่ 2 ได้ ตัวอย่างเช่น หาก ID ของคุณไม่ซ้ำกัน แต่ไม่ใช่ทั่วทั้งแอป แต่อยู่ในประเภทออบเจ็กต์ คุณสามารถใช้ getNormalizationObjectKey: obj => obj.id && obj.type ? obj.id + obj.type : undefined
หรืออะไรที่คล้ายกัน หากเป็นไปไม่ได้ คุณก็สามารถคำนวณส่วนต่อท้ายด้วยตัวเองได้ เช่น:
const getType = obj => { ถ้า (obj.bookTitle) {ส่งคืน 'หนังสือ'; - ถ้า (obj.surname) {return 'ผู้ใช้'; - กลับไม่ได้กำหนด;}; createQueryNormalizer (queryClient, { getNormalizationObjectKey: obj => obj.id && getType(obj) && obj.id + getType(obj),});
ควรปฏิบัติตามจุดที่ 3 เสมอ หากไม่เป็นเช่นนั้น คุณควรขอให้นักพัฒนาแบ็กเอนด์ของคุณรักษาสิ่งต่าง ๆ ให้เป็นมาตรฐานและสม่ำเสมอ เป็นทางเลือกสุดท้าย คุณสามารถแก้ไขคำตอบจากฝั่งของคุณได้
น่าเสียดายที่ไม่ได้หมายความว่าคุณไม่จำเป็นต้องอัปเดตข้อมูลด้วยตนเองอีกต่อไป การอัปเดตบางอย่างยังคงต้องทำด้วยตนเองเหมือนปกติ กล่าวคือ การเพิ่มและลบรายการออกจากอาร์เรย์ ทำไม ลองนึกภาพการกลายพันธุ์ REMOVE_BOOK
หนังสือเล่มนี้อาจมีอยู่ในข้อความค้นหาหลายรายการ ห้องสมุดไม่ทราบว่าคุณต้องการลบออกจากข้อความค้นหาใด เช่นเดียวกับ ADD_BOOK
ห้องสมุดไม่สามารถรู้ได้ว่าควรเพิ่มการสืบค้นหนังสือเล่มใด หรือแม้แต่ดัชนีอาร์เรย์ใด สิ่งเดียวกันสำหรับการดำเนินการเช่น SORT_BOOKS
ปัญหานี้มีผลกับอาร์เรย์ระดับบนสุดเท่านั้น ตัวอย่างเช่น หากคุณมีหนังสือที่มี ID และคีย์อื่นเช่น likedByUsers
หากคุณคืนหนังสือเล่มใหม่พร้อมรายการที่อัปเดตใน likedByUsers
สิ่งนี้จะทำงานอีกครั้งโดยอัตโนมัติ
อย่างไรก็ตาม ในเวอร์ชันอนาคตของไลบรารี่ พร้อมด้วยคำแนะนำเพิ่มเติม ก็เป็นไปได้ที่จะทำการอัปเดตข้างต้นได้เช่นกัน!
หากคุณสนใจว่า normy
จัดการข้อมูลแบบใด คุณสามารถใช้ตัวเลือก devLogging
ได้:
<QueryNormalizerProvider queryClient={queryClient} NormalizerConfig={{ devLogging: true }}> {children}</QueryNormalizerProvider>
false
โดยค่าเริ่มต้น หากตั้งค่าเป็น true
คุณจะเห็นข้อมูลคอนโซลเมื่อมีการตั้งค่าหรือลบคำค้นหา
โปรดทราบว่าสิ่งนี้ใช้ได้เฉพาะในการพัฒนาแม้ว่าคุณจะผ่าน true
ก็จะไม่มีการบันทึกในการผลิต (เมื่อ process.env.NODE_ENV === 'production'
) โดยปกติแล้ว NODE_ENV
จะถูกตั้งค่าโดยตัวรวมโมดูล เช่น webpack
สำหรับคุณ ดังนั้นคุณอาจไม่จำเป็นต้องกังวลเกี่ยวกับการตั้งค่า NODE_ENV
ด้วยตัวเอง
เช่นเคย การทำให้เป็นอัตโนมัติย่อมต้องเสียค่าใช้จ่าย ในอนาคต สามารถเพิ่มเกณฑ์มาตรฐานบางอย่างได้ แต่สำหรับตอนนี้ การทดสอบด้วยตนเองแสดงให้เห็นว่า เว้นแต่ในข้อมูลของคุณ คุณจะมีออบเจ็กต์ที่ทำให้เป็นมาตรฐานนับหมื่น รายการโอเวอร์เฮดก็ไม่ควรสังเกตเห็นได้ อย่างไรก็ตาม คุณมีวิธีต่างๆ ที่ยืดหยุ่นในการปรับปรุงประสิทธิภาพ:
คุณสามารถทำให้ข้อมูลเป็นมาตรฐานได้เฉพาะการสืบค้นที่มีการอัปเดตข้อมูล และเฉพาะการเปลี่ยนแปลงที่ควรอัปเดตข้อมูล เพียงเท่านี้ คุณก็สามารถทำให้ข้อมูลของคุณเป็นมาตรฐานได้เพียงบางส่วนเท่านั้น ตรวจสอบเอกสารประกอบการบูรณาการวิธีการดำเนินการ
เช่นเดียวกับ 1.
แต่สำหรับการสืบค้นและการเปลี่ยนแปลงที่มีข้อมูลขนาดใหญ่มาก
มีการเพิ่มประสิทธิภาพในตัว ซึ่งจะตรวจสอบข้อมูลจากการตอบสนองการกลายพันธุ์ว่าจริง ๆ แล้วแตกต่างจากข้อมูลในร้านค้าที่ทำให้เป็นมาตรฐานหรือไม่ หากเหมือนกัน แบบสอบถามที่เกี่ยวข้องกันจะไม่ได้รับการอัปเดต ดังนั้นจึงเป็นการดีที่ข้อมูลการกลายพันธุ์จะรวมเฉพาะสิ่งที่อาจแตกต่างกันจริง ๆ ซึ่งสามารถป้องกันการปรับมาตรฐานที่ไม่จำเป็นและการอัปเดตการสืบค้น
อย่าปิดใช้งานตัวเลือก structuralSharing
ในไลบรารีที่รองรับ - หากข้อมูลการสืบค้นหลังการอัปเดตเป็นแบบอ้างอิงเดียวกันกับก่อนการอัพเดต การสืบค้นนี้จะไม่ถูกทำให้เป็นมาตรฐาน นี่เป็นการเพิ่มประสิทธิภาพการทำงานครั้งใหญ่ โดยเฉพาะอย่างยิ่งหลังจากการดึงข้อมูลใหม่เมื่อเน้นใหม่ ซึ่งสามารถอัปเดตหลายข้อความค้นหาพร้อมกันได้ ซึ่งโดยปกติแล้วจะเป็นข้อมูลเดียวกัน
คุณสามารถใช้ฟังก์ชัน getNormalizationObjectKey
เพื่อตั้งค่าทั่วโลกว่าออบเจ็กต์ใดที่ควรทำให้เป็นมาตรฐานจริง ตัวอย่างเช่น:
<QueryNormalizerProvider queryClient={queryClient} NormalizerConfig={{getNormalizationObjectKey: obj => (obj.normalizable ? obj.id : ไม่ได้กำหนด), - {children}</QueryNormalizerProvider>
นอกจากนี้ ในอนาคตจะมีการเพิ่มตัวเลือกเฉพาะด้านประสิทธิภาพเพิ่มเติมอีกด้วย
ปัจจุบันมีการบูรณาการอย่างเป็นทางการสามรายการกับไลบรารีดึงข้อมูล ได้แก่ react-query
, swr
และ rtk-query
ดูเอกสารประกอบเฉพาะสำหรับการผสานรวมเฉพาะ:
ตอบสนองแบบสอบถาม
สว
rtk-แบบสอบถาม
ฉันขอแนะนำให้ลองใช้ตัวอย่างว่าแพ็คเกจนี้สามารถนำมาใช้ในแอปพลิเคชันจริงได้อย่างไร
มีตัวอย่างต่อไปนี้ในปัจจุบัน:
ตอบสนองแบบสอบถาม
ทีอาร์พีซี
สว
rtk-แบบสอบถาม
เอ็มไอที