रीएक्ट में एक रेफ के लिए सही प्रॉपटाइप क्या है?


85

मैं अपने redux स्टोर में एक रेफरी का भंडारण कर रहा हूं और उन घटकों के लिए रेफ को बेनकाब करने के लिए mapStateToProps का उपयोग कर रहा हूं, जिन्हें इसकी पहुंच की आवश्यकता है।

जो संग्रह संग्रहीत है वह ऐसा दिखता है:

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

इस रेफरी के लिए सही प्रचार क्या है?


8
क्योंकि Refs सीरियल करने योग्य नहीं हैं, इसलिए उन्हें Redux स्टोर में रखना एक अच्छा विचार नहीं है। फिर भी, refप्रोप को पास किया गया मान एक ऐसा फ़ंक्शन है जिसमें पहले तर्क के साथ DOM तत्व या नल का संदर्भ होता है। यह एक समारोह है
२३

5
आप के propType लिए उपयोग नहीं कर सकते refs, लेकिन आप इसके लिए उपयोग कर सकते हैं props। चूँकि आप इसे फिर से स्टोर करने के लिए पास कर रहे हैं तो यह एक propतरह से दर्शाया जाता है this.props.myRefToBePutInReduxGlobalStoremyRefToBePutInReduxGlobalStoreनोड का प्रकार PropTypes.nodeहोना चाहिए , इसलिए आपके लिए काम करना चाहिए
कारण

मुझे लगता है कि यह होना चाहिए PropType.objectक्योंकि रेफ मूल रूप से वर्ग उदाहरण है जो ऑब्जेक्ट है। इसलिए जब आप एक तत्व के रूप में रेफरी तत्व पास करते हैं तो यह वस्तु प्रकार का होगा
हृदय मोदी

जवाबों:


96

टी एल; डॉ

यदि आप एक रेफ टाइप करना चाहते हैं जो केवल देशी डोम तत्वों की अपेक्षा करता है, जैसे कि एक divया एक 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) })
])

मूल पोस्ट में वर्णित विशिष्ट मुद्दे का जवाब

ओपी प्रश्न के उदाहरण में, यह रेफ प्रोप प्रकार नहीं है जिसे घोषित करने की आवश्यकता है, लेकिन सामान रिफ द्वारा इंगित किया गया है, और जिसे रेडएक्स का उपयोग करके पास किया जाएगा mapStateToProps। DOM तत्व के लिए प्रोप प्रकार होगा: myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)(यदि यह DOM तत्व है)। हालांकि, मैं:

  1. इसका नाम बदलें myElementToBePutInReduxGlobalStore(एक तत्व रेफरी नहीं है)
  2. रिड्यूस स्टोर के अंदर गैर-धारावाहिक डेटा संग्रहीत करने से बचें
  3. प्रॉक्टर इंजीनियर एसईबी मार्कबेज द्वारा बताए गए प्रॉप्स में पासिंग एलिमेंट्स से बचें

वास्तविक प्रश्न का लंबा उत्तर

प्रश्न: रीएक्ट में रेफ के लिए सही प्रोपेप्ट क्या है?

उदाहरण उपयोग मामला:

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]अपने तर्क के रूप में प्राप्त करेगा (जैसे कि ओपी उदाहरण में)

नोट: ऐतिहासिक रूप से, आप स्ट्रिंग रिफ़ का भी उपयोग कर सकते हैं, लेकिन इसे विरासत माना जाता है और प्रतिक्रिया से हटा दिया जाएगा

दूसरा आइटम काफी सरल है और निम्न प्रोप प्रकार की आवश्यकता है PropTypes.func:।

पहला विकल्प कम स्पष्ट है क्योंकि आप रेफ द्वारा बताए गए तत्व के प्रकार को निर्दिष्ट करना चाह सकते हैं।

कई अच्छे जवाब

ref DOM तत्व की तुलना में कुछ और इंगित कर सकते हैं।

यदि आप पूरी तरह से लचीला होना चाहते हैं:

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

उपर्युक्त सिर्फ वस्तु रेफ w / currentसंपत्ति के आकार को लागू करता है । यह किसी भी तरह के रेफ के लिए हर समय काम करेगा। प्रोप प्रकार का उपयोग करने के उद्देश्य से, जो आपके विकसित होने पर किसी भी विसंगतियों को स्पॉट करने का एक तरीका है , यह संभवतः पर्याप्त है। यह बहुत कम संभावना है कि आकार के साथ एक वस्तु { current: [any] }, और एक refToForwardप्रस्ताव को पारित किया जाता है , एक वास्तविक रेफरी नहीं होगा ।

हालाँकि , आप यह घोषित करना चाह सकते हैं कि आपके घटक को किसी भी प्रकार के रेफ की उम्मीद नहीं है , लेकिन केवल एक निश्चित प्रकार, जिसे देखते हुए इसे उस रेफरी की आवश्यकता है।

मैंने एक सैंडबॉक्स को सेटअप किया है जो रेफरी, यहां तक ​​कि कुछ गैर पारंपरिक घोषित करने के लिए कुछ अलग तरीके दिखा रहा है, और फिर उन्हें अन्य प्रकार के साथ परीक्षण कर रहा है। आप इसे यहाँ पा सकते हैं


यदि आप केवल एक मूल इनपुट तत्व की ओर इशारा करते हुए रेफरी की अपेक्षा करते हैं, तो कोई HTML नहीं Element:

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

यदि आप केवल रिएक्ट क्लास घटक की ओर इशारा करते हुए रेफरी की अपेक्षा करते हैं:

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

यदि आप केवल useImperativeHandleकुछ सार्वजनिक विधि को उजागर करने के लिए एक कार्यात्मक घटक की ओर इशारा करते हुए रेफरी की अपेक्षा करते हैं :

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

नोट: उपरोक्त प्रोप प्रकार दिलचस्प है क्योंकि यह प्रतिक्रिया घटकों और मूल डोम तत्वों को भी कवर करता है, क्योंकि वे सभी आधार जावास्क्रिप्ट विरासत में प्राप्त कर रहे हैं Object


रेफरी के लिए प्रोप प्रकार घोषित करने का कोई एक अच्छा तरीका नहीं है, यह उपयोग पर निर्भर करता है। यदि आपका रेफरी किसी बहुत पहचानी गई चीज की ओर इशारा करता है, तो यह एक विशिष्ट प्रोप प्रकार जोड़ने के लायक हो सकता है। अन्यथा, केवल सामान्य आकार की जाँच करना पर्याप्त लगता है।


सर्वर साइड रेंडरिंग के बारे में ध्यान दें

यदि आपका कोड सर्वर पर चलना है, जब तक कि आप पहले से ही DOM वातावरण को पॉलीफ़िल नहीं करते हैं, Elementया कोई अन्य क्लाइंट-साइड प्रकार undefinedNJJS में नहीं होगा। आप इसका समर्थन करने के लिए निम्नलिखित शिम का उपयोग कर सकते हैं:

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

निम्नलिखित रिएक्ट डॉक्स पृष्ठ रेफरी, ऑब्जेक्ट और कॉलबैक दोनों का उपयोग करने के तरीके के बारे में अधिक जानकारी देते हैं , और हुक का उपयोग कैसे करेंuseRef

उत्तर अपडेट किया गया @Rahul Sagore, @Ferenk Kamra, @svnm और @Kamuela Franco को धन्यवाद


2
यह Elementसर्वर साइड रेंडरिंग पर परिभाषित नहीं है। इसका कोई हल?
राहुल सगोर

अच्छी बात। इस शिम के बारे में क्या: Element = typeof Element === 'undefined' ? function(){} : Element(कुछ गितुब मुद्दे में रयान फ्लोरेंस द्वारा सुझाया गया)। अगर यह आपके लिए काम करता है तो मैं इसे अपने जवाब में जोड़ सकता हूं।
पांडायोलो

मैंने इसका पता लगाया और इसे जोड़ा if (!isBrowser) { global.Element = null; }। मेरे लिए काम किया। isBrowser = typeof window !== 'undefined';
राहुल सगोर

बहुत बढ़िया जवाब। मैं टीएल को पसंद करूंगा; डीआर प्रतिक्रिया के शीर्ष पर होना चाहिए।
कमुला फ्रेंको

12

@ पंडायोलो की पोस्ट के समान,

PropTypes.elementType अब जोड़ा गया है

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

अगर PropTypes> = 15.7.0 PropTypes.elementTypeका उपयोग करके इस PR में 10 फरवरी, 2019 को जोड़ा गया


धन्यवाद @svnm, मैंने इसे दर्शाने के लिए अपना उत्तर अपडेट कर दिया है, जो इसे सरल बनाता है!
पंडायोलो

1
अंत में, यह elementTypeमेरे लिए काम नहीं कर रहा था, इसलिए मैंने वास्तव में विभिन्न प्रकार के घटकों पर प्रोप प्रकारों का एक गुच्छा परीक्षण किया, जो एक सैंडबॉक्स में रेफरी द्वारा इंगित किया जा सकता है। यहाँ परिणाम हैं: codesandbox.io/s/loving-benz-w6fbh । मुझे यकीन नहीं है कि मैंने सभी संभावनाओं को कवर किया है, लेकिन ऐसा लगता है कि DOM तत्व के लिए सही प्रोपेप्ट है instanceOf(Element)(या object), एक वर्ग के लिए यह instanceOf(Component)(या object) है और इसका उपयोग करने वाले कार्यात्मक घटक के विशिष्ट उपयोग के मामले में useImperativeHandleहै object। विचार?
पंडायोलो

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) }),
  ]),
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.