संपादित करें : ES6 अद्यतन उदाहरणों के लिए अंतिम उदाहरण देखें।
यह उत्तर सीधे माता-पिता के बच्चे के रिश्ते के मामले को संभालता है। जब माता-पिता और बच्चे में संभावित रूप से बहुत अधिक मध्यस्थ होते हैं, तो इस उत्तर की जांच करें ।
अन्य समाधान बिंदु याद आ रहे हैं
जबकि वे अभी भी ठीक काम करते हैं, अन्य उत्तर कुछ महत्वपूर्ण याद कर रहे हैं।
पुनरावृत्ति में घटनाओं का उपयोग करके अपने माता-पिता के लिए एक बच्चे के सहारा को पास करने का एक सरल तरीका नहीं है?
माता-पिता के पास पहले से ही वह बच्चा है! : यदि बच्चे के पास एक प्रॉप है, तो यह इसलिए है क्योंकि उसके माता-पिता ने बच्चे को वह प्रॉप प्रदान किया है! आप बच्चे को माता-पिता के पास वापस क्यों भेजना चाहते हैं, जबकि माता-पिता के पास स्पष्ट रूप से वह प्रस्ताव है?
बेहतर कार्यान्वयन
बच्चा : यह वास्तव में उससे ज्यादा जटिल नहीं है।
var Child = React.createClass({
render: function () {
return <button onClick={this.props.onClick}>{this.props.text}</button>;
},
});
एकल बच्चे के साथ अभिभावक : मूल्य का उपयोग करके यह बच्चे के पास जाता है
var Parent = React.createClass({
getInitialState: function() {
return {childText: "Click me! (parent prop)"};
},
render: function () {
return (
<Child onClick={this.handleChildClick} text={this.state.childText}/>
);
},
handleChildClick: function(event) {
// You can access the prop you pass to the children
// because you already have it!
// Here you have it in state but it could also be
// in props, coming from another parent.
alert("The Child button text is: " + this.state.childText);
// You can also access the target of the click here
// if you want to do some magic stuff
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
बच्चों की सूची के साथ अभिभावक : आपके पास अभी भी वह सब कुछ है जो आपको माता-पिता की आवश्यकता है और बच्चे को अधिक जटिल बनाने की आवश्यकता नहीं है।
var Parent = React.createClass({
getInitialState: function() {
return {childrenData: [
{childText: "Click me 1!", childNumber: 1},
{childText: "Click me 2!", childNumber: 2}
]};
},
render: function () {
var children = this.state.childrenData.map(function(childData,childIndex) {
return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
}.bind(this));
return <div>{children}</div>;
},
handleChildClick: function(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
इसका उपयोग करना this.handleChildClick.bind(null,childIndex)
और फिर उपयोग करना भी संभव हैthis.state.childrenData[childIndex]
ध्यान दें कि हम एक null
संदर्भ के साथ बाध्यकारी हैं क्योंकि अन्यथा प्रतिक्रिया इसके ऑटोबाइंडिंग सिस्टम से संबंधित चेतावनी जारी करती है। नल का उपयोग करने का मतलब है कि आप फ़ंक्शन संदर्भ को बदलना नहीं चाहते हैं। यह भी देखें ।
अन्य उत्तरों में इनकैप्सुलेशन और कपलिंग के बारे में
यह मेरे लिए कपलिंग और इनकैप्सुलेशन की अवधि में एक बुरा विचार है:
var Parent = React.createClass({
handleClick: function(childComponent) {
// using childComponent.props
// using childComponent.refs.button
// or anything else using childComponent
},
render: function() {
<Child onClick={this.handleClick} />
}
});
प्रॉप्स का उपयोग करना : जैसा कि मैंने ऊपर बताया है, आपके पास पहले से ही माता-पिता में प्रॉप्स हैं इसलिए प्रॉप्स तक पहुंचने के लिए पूरे बच्चे के घटक को पास करना बेकार है।
Refs का उपयोग करना : आपके पास पहले से ही ईवेंट में क्लिक लक्ष्य है, और ज्यादातर मामलों में यह पर्याप्त है। इसके अलावा, आप बच्चे पर सीधे रेफरी का उपयोग कर सकते हैं:
<Child ref="theChild" .../>
और माता-पिता के साथ DOM नोड का उपयोग करें
React.findDOMNode(this.refs.theChild)
अधिक उन्नत मामलों के लिए जहां आप बच्चे के कई रेफरी अभिभावक तक पहुंचना चाहते हैं, बच्चा कॉलबैक में सभी डोम नोड्स को सीधे पास कर सकता है।
घटक के पास एक इंटरफ़ेस (प्रॉपर) है और माता-पिता को बच्चे के आंतरिक कामकाज के बारे में कुछ भी ग्रहण नहीं करना चाहिए, जिसमें इसकी आंतरिक डोम संरचना भी शामिल है या जो डोम नोड्स घोषित करता है वह इसके लिए रेफरी है। एक बच्चे के रेफरी का उपयोग करने वाले माता-पिता का मतलब है कि आप कसकर 2 घटकों को जोड़ते हैं।
समस्या का वर्णन करने के लिए, मैं शैडो डोम के बारे में यह उद्धरण लूंगा , जिसका उपयोग ब्राउज़रों के अंदर स्लाइडर्स, स्क्रॉलबार, वीडियो प्लेयर जैसी चीजों को प्रस्तुत करने के लिए किया जाता है ...:
उन्होंने आपके, वेब डेवलपर के बीच एक सीमा बनाई और कार्यान्वयन विवरणों पर विचार किया जा सकता है, इस प्रकार आप के लिए दुर्गम है। हालांकि, ब्राउज़र इस वसीयत में सीमा पार कर सकता है। इस सीमा के साथ, वे सभी HTML तत्वों को एक ही अच्छी-पुरानी वेब तकनीकों का उपयोग करने में सक्षम कर रहे थे, जैसे आप चाहते हैं, वैसे ही divs और spans में से।
समस्या यह है कि यदि आप बच्चे के विवरण को माता-पिता में लीक होने देते हैं, तो आप माता-पिता को प्रभावित किए बिना बच्चे को फिर से तैयार करना बहुत कठिन बना देते हैं। यह एक पुस्तकालय लेखक के रूप में (या शैडो डोम के साथ एक ब्राउज़र संपादक के रूप में) इसका मतलब यह बहुत खतरनाक है क्योंकि आप क्लाइंट को बहुत अधिक उपयोग करने देते हैं, जिससे रेट्रोकोमपेबिलिटी को तोड़ने के बिना कोड को अपग्रेड करना बहुत कठिन हो जाता है।
यदि Chrome ने अपने स्क्रॉलबार को कार्यान्वित किया है, तो ग्राहक को उस स्क्रॉलबार के आंतरिक डोम नोड्स का उपयोग करने की अनुमति देता है, तो इसका मतलब है कि क्लाइंट के पास बस उस स्क्रॉलबार को तोड़ने की संभावना हो सकती है, और क्रोम को ऑटो-अपडेट करने के बाद ऐप आसानी से टूट जाएगा। स्क्रॉलबार ... इसके बजाय, वे केवल कुछ सुरक्षित चीजों तक पहुंच देते हैं जैसे कि सीएसएस के साथ स्क्रॉलबार के कुछ हिस्सों को कस्टमाइज़ करना।
किसी और चीज के इस्तेमाल के बारे में
कॉलबैक में पूरे घटक को पारित करना खतरनाक है और नौसिखिया डेवलपर्स को कॉल करने childComponent.setState(...)
या childComponent.forceUpdate()
माता-पिता के अंदर नए चर को असाइन करने, या ऐसा करने के लिए बहुत अजीब काम कर सकता है, जिससे पूरे ऐप के बारे में तर्क करना मुश्किल हो जाता है।
संपादित करें: ES6 उदाहरण
अब जितने लोग ES6 का उपयोग करते हैं, यहाँ ES6 वाक्य रचना के लिए एक ही उदाहरण हैं
बच्चा बहुत सरल हो सकता है:
const Child = ({
onClick,
text
}) => (
<button onClick={onClick}>
{text}
</button>
)
माता-पिता या तो एक वर्ग हो सकते हैं (और यह अंततः राज्य का प्रबंधन खुद कर सकते हैं, लेकिन मैं इसे यहां सहारा के रूप में पारित कर रहा हूं:
class Parent1 extends React.Component {
handleChildClick(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
render() {
return (
<div>
{this.props.childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => this.handleChildClick(child,e)}
/>
))}
</div>
);
}
}
लेकिन इसे सरल भी किया जा सकता है, अगर इसे राज्य का प्रबंधन करने की आवश्यकता नहीं है:
const Parent2 = ({childrenData}) => (
<div>
{childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => {
alert("The Child button data is: " + child.childText + " - " + child.childNumber);
alert("The Child HTML is: " + e.target.outerHTML);
}}
/>
))}
</div>
)
JsFiddle
PERF चेतावनी (ES5 / ES6 पर लागू): यदि आप उपयोग कर रहे हैं PureComponent
या shouldComponentUpdate
, उपरोक्त कार्यान्वयन डिफ़ॉल्ट रूप से अनुकूलित नहीं होंगे क्योंकि onClick={e => doSomething()}
रेंडर चरण के दौरान सीधे उपयोग करते हुए , या बाइंडिंग करते हैं, क्योंकि यह पेरेंट रेंडर करने के लिए हर बार एक नया फ़ंक्शन बनाएगा। यदि आपके ऐप में यह एक अड़चन है, तो आप बच्चों को डेटा पास कर सकते हैं, और इसे "स्थिर" कॉलबैक (पैरेंट क्लास पर सेट, और this
क्लास कंस्ट्रक्टर में बाइंड किया गया) के अंदर रिइंस्टॉल PureComponent
कर सकते हैं, ताकि ऑप्टिमाइज़ेशन किक कर सके, या आप अपने खुद के कार्यान्वित कर सकते हैं shouldComponentUpdate
और सहारा तुलना चेक में कॉलबैक को अनदेखा कर सकते हैं।
आप पुन: उपयोग की गई लाइब्रेरी का भी उपयोग कर सकते हैं , जो ठीक ट्यून किए गए अनुकूलन प्राप्त करने के लिए उच्च आदेश घटक प्रदान करते हैं:
// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}
// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)
// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)
इस स्थिति में आप बाल घटक को उपयोग करके अनुकूलित कर सकते हैं:
const OptimizedChild = onlyUpdateForKeys(['text'])(Child)