का उपयोग करते हुए children
const Wrapper = ({children}) => (
<div>
<div>header</div>
<div>{children}</div>
<div>footer</div>
</div>
);
const App = ({name}) => <div>Hello {name}</div>;
const WrappedApp = ({name}) => (
<Wrapper>
<App name={name}/>
</Wrapper>
);
render(<WrappedApp name="toto"/>,node);
इसे transclusion
एंगुलर के नाम से भी जाना जाता है।
children
प्रतिक्रिया में एक विशेष प्रोप है और इसमें आपके घटक के टैग के अंदर क्या है (यहां <App name={name}/>
अंदर है Wrapper
, इसलिए यह है)children
ध्यान दें कि आपको आवश्यक रूप से उपयोग करने की आवश्यकता नहीं है children
, जो एक घटक के लिए अद्वितीय है, और आप चाहें तो सामान्य प्रॉप्स का भी उपयोग कर सकते हैं या प्रॉप्स और बच्चों को मिला सकते हैं:
const AppLayout = ({header,footer,children}) => (
<div className="app">
<div className="header">{header}</div>
<div className="body">{children}</div>
<div className="footer">{footer}</div>
</div>
);
const appElement = (
<AppLayout
header={<div>header</div>}
footer={<div>footer</div>}
>
<div>body</div>
</AppLayout>
);
render(appElement,node);
यह कई usecases के लिए सरल और ठीक है, और मैं इसे अधिकांश उपभोक्ता ऐप्स के लिए सुझाऊंगा।
प्रस्तुत करना
किसी घटक को रेंडर फ़ंक्शंस पास करना संभव है, इस पैटर्न को आम तौर पर कहा जाता है render prop
, और children
उस कॉलबैक को प्रदान करने के लिए अक्सर प्रोप का उपयोग किया जाता है।
यह पैटर्न वास्तव में लेआउट के लिए नहीं है। आवरण घटक का उपयोग आमतौर पर कुछ राज्य को रखने और प्रबंधित करने के लिए किया जाता है और इसे अपने रेंडर कार्यों में इंजेक्ट किया जाता है।
काउंटर उदाहरण:
const Counter = () => (
<State initial={0}>
{(val, set) => (
<div onClick={() => set(val + 1)}>
clicked {val} times
</div>
)}
</State>
);
आप और भी अधिक फैंसी प्राप्त कर सकते हैं और एक वस्तु भी प्रदान कर सकते हैं
<Promise promise={somePromise}>
{{
loading: () => <div>...</div>,
success: (data) => <div>{data.something}</div>,
error: (e) => <div>{e.message}</div>,
}}
</Promise>
ध्यान दें कि आपको उपयोग करने की आवश्यकता नहीं है children
, यह स्वाद / एपीआई का मामला है।
<Promise
promise={somePromise}
renderLoading={() => <div>...</div>}
renderSuccess={(data) => <div>{data.something}</div>}
renderError={(e) => <div>{e.message}</div>}
/>
आज तक, कई पुस्तकालय रेंडर प्रॉप्स (प्रतिक्रिया संदर्भ, प्रतिक्रिया-गति, अपोलो ...) का उपयोग कर रहे हैं क्योंकि लोग इस एपीआई को एचओसी की तुलना में अधिक आसान पाते हैं। प्रतिक्रिया-पॉवरप्लग सरल रेंडर-प्रोप घटकों का एक संग्रह है। प्रतिक्रिया-अपनाने से आपको रचना करने में मदद मिलती है।
उच्च-क्रम के घटक (HOC)।
const wrapHOC = (WrappedComponent) => {
class Wrapper extends React.PureComponent {
render() {
return (
<div>
<div>header</div>
<div><WrappedComponent {...this.props}/></div>
<div>footer</div>
</div>
);
}
}
return Wrapper;
}
const App = ({name}) => <div>Hello {name}</div>;
const WrappedApp = wrapHOC(App);
render(<WrappedApp name="toto"/>,node);
एक उच्च-आदेश घटक / HOC आम तौर पर एक फ़ंक्शन होता है जो एक घटक लेता है और एक नया घटक देता है।
हायर-ऑर्डर कंपोनेंट का उपयोग करने की तुलना में अधिक प्रदर्शनकारी हो सकता है children
या render props
, क्योंकि आवरण में शॉर्ट-सर्किट करने की क्षमता हो सकती है जिससे रेंडरिंग एक कदम आगे निकल जाए shouldComponentUpdate
।
यहां हम उपयोग कर रहे हैं PureComponent
। ऐप को री-रेंडर करते समय, यदि WrappedApp
नाम प्रोप समय के साथ नहीं बदलता है, तो रैपर में यह कहने की क्षमता होती है कि "मुझे प्रस्तुत करने की आवश्यकता नहीं है क्योंकि प्रॉप्स (वास्तव में, नाम) पहले की तरह ही हैं"। children
ऊपर आधारित समाधान के साथ , भले ही आवरण हो PureComponent
, यह मामला नहीं है क्योंकि बच्चों के तत्व को हर बार माता-पिता प्रदान करते हैं, जिसका अर्थ है कि आवरण हमेशा शुद्ध होगा, भले ही लिपटे घटक शुद्ध हो। एक बैबल प्लगइन है जो इसे कम करने और children
समय के साथ एक निरंतर तत्व सुनिश्चित करने में मदद कर सकता है ।
निष्कर्ष
उच्च-क्रम के घटक आपको बेहतर प्रदर्शन दे सकते हैं। यह इतना जटिल नहीं है, लेकिन यह निश्चित रूप से पहली बार में अविश्वसनीय लगता है।
इसे पढ़ने के बाद अपने पूरे कोडबेस को HOC पर माइग्रेट न करें। बस याद रखें कि अपने ऐप के महत्वपूर्ण रास्तों पर आप प्रदर्शन कारणों से रनटाइम रैपरों के बजाय HOCs का उपयोग करना चाह सकते हैं, खासकर यदि उसी आवरण का उपयोग कई बार किया जाए तो यह HOC बनाने पर विचार करने लायक होता है।
Redux पहले एक रनटाइम रैपर पर इस्तेमाल होता था <Connect>
और बाद में connect(options)(Comp)
प्रदर्शन कारणों से HOC में बदल जाता था (डिफ़ॉल्ट रूप से, रैपर शुद्ध और उपयोग होता है shouldComponentUpdate
)। इस उत्तर में मैं जो प्रकाश डालना चाहता था, उसका सही चित्रण है।
ध्यान दें कि यदि किसी कंपोनेंट में रेंडर-प्रोप एपीआई है, तो आमतौर पर उसके ऊपर एक एचओसी बनाना आसान होता है, इसलिए यदि आप एक कार्यकारी लेखक हैं, तो आपको पहले रेंडर प्रोप एपीआई लिखना चाहिए, और अंततः एचओसी संस्करण की पेशकश करनी चाहिए। यह वही है जो अपोलो <Query>
रेंडर-प्रोप घटक के साथ करता है , और graphql
एचओसी इसका उपयोग करता है।
व्यक्तिगत रूप से, मैं दोनों का उपयोग करता हूं, लेकिन जब संदेह होता है तो मैं HOC पसंद करता हूं क्योंकि:
- प्रॉपर
compose(hoc1,hoc2)(Comp)
रेंडर करने की तुलना में उन्हें ( ) कंपोज करना ज्यादा मुहावरेदार है
- यह मुझे बेहतर प्रदर्शन दे सकता है
- मैं प्रोग्रामिंग की इस शैली से परिचित हूं
मैं अपने पसंदीदा टूल के HOC संस्करणों का उपयोग / निर्माण करने में संकोच नहीं करता:
- प्रतिक्रिया का
Context.Consumer
COMP
- अनकहा की
Subscribe
- प्रोप प्रस्तुत
graphql
करने के बजाय अपोलो के एचओसी का उपयोग करनाQuery
मेरी राय में, कभी-कभी रेंडर प्रॉप्स कोड को अधिक पठनीय बनाते हैं, कभी-कभी कम भी ... मैं अपने पास मौजूद बाधाओं के अनुसार सबसे व्यावहारिक समाधान का उपयोग करने की कोशिश करता हूं। कभी-कभी प्रदर्शन की तुलना में पठनीयता अधिक महत्वपूर्ण होती है, कभी-कभी नहीं। बुद्धिमानी से चुनें और सब कुछ रेंडर-प्रॉप में परिवर्तित करने के 2018 की प्रवृत्ति का पालन न करें।