proptype ที่ถูกต้องสำหรับ ref ใน React คืออะไร?


87

ฉันกำลังจัดเก็บการอ้างอิงในร้านค้า redux ของฉันและใช้ mapStateToProps เพื่อแสดงการอ้างอิงสำหรับส่วนประกอบที่จำเป็นต้องเข้าถึง

การอ้างอิงที่จัดเก็บมีลักษณะดังนี้:

ref={node => this.myRefToBePutInReduxGlobalStore = node}

propType ที่ถูกต้องสำหรับการอ้างอิงนี้คืออะไร?


8
เนื่องจากการอ้างอิงไม่สามารถต่อเนื่องกันได้จึงไม่ควรนำไปไว้ในร้าน Redux อย่างไรก็ตามค่าที่ส่งไปยังrefprop คือฟังก์ชันที่มีอาร์กิวเมนต์แรกอ้างอิงถึงองค์ประกอบ DOM หรือ null มันเป็นฟังก์ชั่น
ตื่น

5
คุณไม่สามารถใช้propType สำหรับrefsแต่คุณสามารถใช้สำหรับprops. เนื่องจากคุณจะผ่านมันไปเก็บ Redux แล้วก็แสดงเป็นเหมือนprop ควรเป็นประเภทของโหนดดังนั้นควรจะเหมาะกับคุณthis.props.myRefToBePutInReduxGlobalStoremyRefToBePutInReduxGlobalStorePropTypes.node
The Reason

ฉันคิดว่ามันควรจะเป็นPropType.objectเพราะโดยพื้นฐานแล้ว ref เป็นอินสแตนซ์คลาสซึ่งเป็นวัตถุ ดังนั้นเมื่อคุณส่งองค์ประกอบอ้างอิงเป็นอุปกรณ์ประกอบฉากมันจะเป็นประเภทวัตถุ
Hriday Modi

คำตอบ:


101

TL; ดร

หากคุณต้องการ prop ให้พิมพ์ ref ที่คาดหวังเฉพาะองค์ประกอบ DOM ดั้งเดิมเช่น a divหรือ an inputคำจำกัดความที่ถูกต้องมีดังต่อไปนี้:

refProp: PropTypes.oneOfType([
    // Either a function
    PropTypes.func, 
    // Or the instance of a DOM native element (see the note about SSR)
    PropTypes.shape({ current: PropTypes.instanceOf(Element) })
])

คำตอบสำหรับปัญหาเฉพาะที่อธิบายไว้ในโพสต์ต้นฉบับ

ในตัวอย่างคำถามของ OP ก็ไม่ได้โทษประเภทเสาที่ความต้องการที่จะได้รับการประกาศ แต่สิ่งที่ชี้ให้เห็นโดนโทษและที่จะถูกส่งผ่านจาก Redux mapStateToPropsใช้ ประเภท Prop สำหรับองค์ประกอบ DOM จะเป็น: myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)(ถ้าเป็นองค์ประกอบ DOM) แม้ว่าฉันจะ:

  1. เปลี่ยนชื่อเป็นmyElementToBePutInReduxGlobalStore(องค์ประกอบไม่ใช่การอ้างอิง)
  2. หลีกเลี่ยงการจัดเก็บข้อมูลที่ไม่ต่ออนุกรมไว้ในที่เก็บ redux
  3. หลีกเลี่ยงการส่งผ่านองค์ประกอบในอุปกรณ์ประกอบฉากตามคำอธิบายของวิศวกรปฏิกิริยา Seb Markbage

คำตอบยาวสำหรับคำถามจริง

ถาม: proptype ที่ถูกต้องสำหรับ ref ใน React คืออะไร?

ตัวอย่างการใช้งาน:

function FancyInput({ inputRef }) {
    return (
        <div className="fancy">
            Fancy input
            <input ref={inputRef} />
        </div>
    )
}

FancyInput.propTypes = {
    inputRef: ???   // What is the correct prop type here?
}

function App(props) {
    const inputRef = React.useRef()
    useLayoutEffect(function focusWhenStuffChange() {
        inputRef.current?.focus()
    }, [props.stuff])
    return <FancyInput inputRef={inputRef} />
}

วันนี้มีการอ้างอิงสองประเภทในการตอบสนอง:

  1. วัตถุที่มีลักษณะเช่นนี้{ current: [something] }มักสร้างขึ้นโดยตัว React.createRef()ช่วยหรือReact.useRef()ตะขอ
  2. ฟังก์ชันเรียกกลับซึ่งจะได้รับ[something]เป็นอาร์กิวเมนต์ (เช่นเดียวกับในตัวอย่าง OP)

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

PropTypes.funcรายการที่สองค่อนข้างง่ายและต้องใช้ไม้ค้ำยันประเภทต่อไปนี้:

ตัวเลือกแรกมีความชัดเจนน้อยกว่าเนื่องจากคุณอาจต้องการระบุประเภทขององค์ประกอบที่อ้างถึง

คำตอบที่ดีมากมาย

ref สามารถชี้ไปที่อย่างอื่นที่ไม่ใช่องค์ประกอบ DOM

หากคุณต้องการความยืดหยุ่นโดยสิ้นเชิง:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.any })
])

ข้างต้นบังคับใช้เพียงรูปร่างของวัตถุอ้างอิง w / currentคุณสมบัติ มันจะทำงานตลอดเวลาสำหรับการอ้างอิงทุกประเภท สำหรับวัตถุประสงค์ในการใช้ prop type ซึ่งเป็นวิธีการตรวจจับความไม่สอดคล้องกันเมื่อคุณพัฒนาสิ่งนี้อาจเพียงพอแล้ว ดูเหมือนว่าไม่น่าเป็นไปได้มากที่วัตถุที่มีรูปร่าง{ current: [any] }และถูกส่งต่อไปยังrefToForwardเสาจะไม่ใช่การอ้างอิงที่แท้จริง

อย่างไรก็ตามคุณอาจต้องการประกาศว่าส่วนประกอบของคุณไม่ได้คาดหวังการอ้างอิงใด ๆแต่มีเพียงบางประเภทเท่านั้นที่ระบุสิ่งที่ต้องการอ้างอิง

ฉันได้ตั้งค่าแซนด์บ็อกซ์ซึ่งแสดงวิธีต่างๆในการประกาศการอ้างอิงแม้บางอย่างจะไม่ใช่แบบธรรมดาจากนั้นทดสอบด้วยเสาหลายประเภท คุณสามารถพบได้ที่นี่


หากคุณคาดหวังเฉพาะการอ้างอิงที่ชี้ไปยังองค์ประกอบอินพุตดั้งเดิมไม่ใช่HTML ใด ๆElement :

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(HTMLInputElement) })
])

หากคุณคาดหวังเพียงการอ้างอิงที่ชี้ไปที่องค์ประกอบของคลาส React:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(Component) })
])

หากคุณคาดหวังเพียงการอ้างอิงที่ชี้ไปยังส่วนประกอบที่ใช้งานได้โดยใช้useImperativeHandleเพื่อเปิดเผยวิธีการสาธารณะบางอย่าง:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.object })
])

หมายเหตุ: ประเภทของเสาด้านบนนั้นน่าสนใจเพราะมันครอบคลุมส่วนประกอบปฏิกิริยาและองค์ประกอบ DOM ดั้งเดิมด้วยเนื่องจากทั้งหมดนี้สืบทอดจาวาสคริปต์พื้นฐาน Object


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


หมายเหตุเกี่ยวกับการแสดงผลฝั่งเซิร์ฟเวอร์

หากโค้ดของคุณต้องทำงานบนเซิร์ฟเวอร์เว้นแต่คุณจะเติมสภาพแวดล้อม DOM แบบ polyfill Elementหรือประเภทฝั่งไคลเอ็นต์อื่น ๆ จะอยู่undefinedใน NodeJS คุณสามารถใช้ shim ต่อไปนี้เพื่อรองรับ:

Element = typeof Element === 'undefined' ? function(){} : Element

หน้า React Docs ต่อไปนี้ให้ข้อมูลเชิงลึกมากขึ้นเกี่ยวกับวิธีใช้ refs ทั้ง object และ callbacksและวิธีใช้useRefhook

คำตอบที่อัปเดตแล้วขอบคุณ @Rahul Sagore, @Ferenk Kamra, @svnm และ @Kamuela Franco


2
มันจะช่วยให้Elementไม่ได้ถูกกำหนดในด้านการแสดงผลเซิร์ฟเวอร์ วิธีแก้ปัญหาใด ๆ
Rahul Sagore

จุดดี. สิ่งนี้เกี่ยวกับ shim: Element = typeof Element === 'undefined' ? function(){} : Element(แนะนำโดย Ryan Florence ในปัญหา github บางอย่าง) ถ้ามันเหมาะกับคุณฉันสามารถเพิ่มคำตอบของฉันได้
Pandaiolo

if (!isBrowser) { global.Element = null; }ฉันคิดว่ามันออกและบันทึกนี้ ทำงานให้ฉัน isBrowser = typeof window !== 'undefined';
Rahul Sagore

คำตอบที่ดี ฉันชอบ TL; DR อยู่ที่ด้านบนของการตอบสนอง
Kamuela Franco

12

คล้ายกับโพสต์ของ @ Pandaiolo

PropTypes.elementType ได้รับการเพิ่มแล้ว

forwardedRef: PropTypes.oneOfType([
  PropTypes.func,
  PropTypes.shape({ current: PropTypes.elementType })
]),

หากใช้ PropTypes> = 15.7.0 PropTypes.elementTypeถูกเพิ่มเมื่อวันที่ 10 กุมภาพันธ์ 2019 ในPR นี้


ขอบคุณ @svnm ฉันได้อัปเดตคำตอบเพื่อสะท้อนสิ่งนี้ซึ่งทำให้ง่ายขึ้น!
Pandaiolo

1
ในท้ายที่สุดนั่นelementTypeก็ไม่ได้ผลสำหรับฉันดังนั้นฉันจึงทดสอบประเภทของเสากับส่วนประกอบประเภทต่างๆที่อ้างอิงได้ในแซนด์บ็อกซ์ นี่คือผลที่ได้คือ: codesandbox.io/s/loving-benz-w6fbh ผมไม่แน่ใจว่าผมได้รับการคุ้มครองเป็นไปได้ทั้งหมด แต่ก็ดูเหมือนว่า proptype ที่ถูกต้องสำหรับองค์ประกอบ DOM เป็นinstanceOf(Element)(หรือobject) สำหรับการเรียนก็เป็นinstanceOf(Component)(หรือobject) และสำหรับกรณีการใช้งานที่เฉพาะเจาะจงขององค์ประกอบการทำงานโดยใช้มันเป็นuseImperativeHandle objectความคิด?
Pandaiolo

9

ฉันตรวจสอบวิธีที่ต้องการเท่านั้นและเนื่องจากPropType.objectไม่มีค่ามากฉันจึงใช้สิ่งนี้:

PropTypes.shape({ current: PropTypes.instanceOf(Element) })

1

ฉันตรวจสอบคำตอบข้างต้นทั้งหมดแล้ว แต่ได้รับคำเตือนจากปฏิกิริยาดังนั้นฉันจึงค้นคว้าข้อมูลมากมายและได้คำตอบที่ถูกต้อง

import React, { Component } from 'react';

ComponentName.propTypes = {
  reference: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.shape({ current: PropTypes.instanceOf(Component) }),
  ]),
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.