माता-पिता से बच्चे की विधि को बुलाओ


473

मेरे दो घटक हैं।

  1. जनक घटक
  2. बाल घटक

मैं माता-पिता से बच्चे की विधि को कॉल करने की कोशिश कर रहा था, मैंने इस तरह से कोशिश की, लेकिन परिणाम नहीं मिल सका

class Parent extends Component {
  render() {
    return (
      <Child>
        <button onClick={Child.getAlert()}>Click</button>
      </Child>
      );
    }
  }

class Child extends Component {
  getAlert() {
    alert('clicked');
  }

  render() {
    return (
      <h1 ref="hello">Hello</h1>
    );
  }
}

क्या माता-पिता से बच्चे की विधि को कॉल करने का एक तरीका है?

नोट: बाल और अभिभावक घटक दो अलग-अलग फ़ाइलों में हैं


हालाँकि मुझे इसमें बहुत देरी है, मैं रिएक्ट भी सीख रहा हूँ, इसलिए मैं उस मामले के बारे में जानना चाहूँगा जिसमें एक अभिभावक को चाइल्ड मेथड को कॉल करना होगा। क्या आप समझाएंगे?
अक्षय राऊत

किसी को पता है कि यह तीर के कार्यों से कैसे होता है? stackoverflow.com/questions/60015693/…
थॉमस सेगाटो

@ अक्षय अक्षय एक अच्छा उपयोग-मामला: रीसेट और कार्यों को प्रस्तुत करने के साथ एक सामान्य उद्देश्य फॉर्म, जिसमें से बाद में फॉर्म मान वापस आ जाते हैं।
जूलियन के

जवाबों:


702

सबसे पहले, मुझे यह व्यक्त करना चाहिए कि यह आमतौर पर रिएक्ट भूमि में चीजों के बारे में जाने का तरीका नहीं है। आमतौर पर आप जो करना चाहते हैं वह प्रॉप्स में बच्चों को फंक्शनलिटी पास करना होता है, और ईवेंट्स (या इससे बेहतर:) में बच्चों के नोटिफिकेशन को पास करना होता है dispatch

लेकिन अगर आपको बच्चे के घटक पर एक अनिवार्य विधि का पर्दाफाश करना चाहिए , तो आप रिफ का उपयोग कर सकते हैं । याद रखें कि यह एक पलायन हैच है और आमतौर पर इंगित करता है कि एक बेहतर डिजाइन उपलब्ध है।

पहले, Refs केवल कक्षा-आधारित घटकों के लिए समर्थित थे। रिएक्ट हुक के आगमन के साथ , अब ऐसा नहीं है

हुक और फ़ंक्शन घटकों का उपयोग करना ( >= react@16.8)

const { forwardRef, useRef, useImperativeHandle } = React;

// We need to wrap component in `forwardRef` in order to gain
// access to the ref object that is assigned using the `ref` prop.
// This ref is passed as the second parameter to the function component.
const Child = forwardRef((props, ref) => {

  // The component instance will be extended
  // with whatever you return from the callback passed
  // as the second argument
  useImperativeHandle(ref, () => ({

    getAlert() {
      alert("getAlert from Child");
    }

  }));

  return <h1>Hi</h1>;
});

const Parent = () => {
  // In order to gain access to the child component instance,
  // you need to assign it to a `ref`, so we call `useRef()` to get one
  const childRef = useRef();

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={() => childRef.current.getAlert()}>Click</button>
    </div>
  );
};

ReactDOM.render(
  <Parent />,
  document.getElementById('root')
);
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

<div id="root"></div>

के लिए दस्तावेज़ useImperativeHandle()है यहां :

useImperativeHandleउपयोग करते समय मूल मान को उजागर करने वाले उदाहरण मान को अनुकूलित करता है ref

कक्षा घटकों ( >= react@16.4) का उपयोग करना

const { Component } = React;

class Parent extends Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onClick = () => {
    this.child.current.getAlert();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('getAlert from Child');
  }

  render() {
    return <h1>Hello</h1>;
  }
}

ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>

विरासत एपीआई ( <= react@16.3)

ऐतिहासिक उद्देश्यों के लिए, यहां 16.3 से पहले आपके द्वारा कॉलबैक-आधारित शैली का उपयोग किया जाएगा।

const { Component } = React;
const { render } = ReactDOM;

class Parent extends Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('clicked');
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}


render(
  <Parent />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>


23
मैं थक गया, लेकिन इस त्रुटि के साथ समाप्त हो गया "_this2.refs.child.getAlert एक कार्य नहीं है"
N8FURY

22
ऐसा इसलिए है क्योंकि connectएक उच्च क्रम घटक देता है जो आपके मूल उदाहरण को लपेटता है। getWrappedInstance()अपने मूल घटक को प्राप्त करने के लिए आपको पहले जुड़े घटक पर कॉल करना होगा । तब आप उस पर उदाहरण के तरीके कह सकते हैं।
19

16
यह वास्तव में एक अच्छा पैटर्न नहीं है। स्ट्रिंग रिफ न होने का उल्लेख किया गया है। बच्चे के घटक में प्रॉपर पास करना बेहतर है और फिर माता-पिता की स्थिति को बदलने के लिए माता-पिता में एक बटन क्लिक करें, और बच्चे में एक राज्य आइटम पास करें जो बच्चे को ट्रिगर करेगा componentWillReceiveProps, और ट्रिगर के रूप में उपयोग करेगा।
ffxsam

7
नहीं, यह आमतौर पर सबसे अच्छा पैटर्न नहीं है, यह भागने की हैच की अधिक है जब आपको इसकी आवश्यकता होती है, और इसका उपयोग केवल आपात स्थितियों में किया जाना चाहिए। इसके अलावा, यह उत्तर तब लिखा गया था जब स्ट्रिंग रेफरी अभी भी आसपास थे, और आप सही हैं कि वे इन दिनों चीजों को करने का "सही" तरीका नहीं हैं।
रॉसिडीया

34
अगर सबसे अच्छा अभ्यास है बच्चे के घटक के तरीके को कॉल करने के रूप में कुछ सरल करने के लिए तर्क का चक्रव्यूह बनाना है - तो मैं सर्वोत्तम अभ्यास से असहमत हूं।
आचमन

149

आप यहां एक और पैटर्न का उपयोग कर सकते हैं:

class Parent extends Component {
 render() {
  return (
    <div>
      <Child setClick={click => this.clickChild = click}/>
      <button onClick={() => this.clickChild()}>Click</button>
    </div>
  );
 }
}

class Child extends Component {
 constructor(props) {
    super(props);
    this.getAlert = this.getAlert.bind(this);
 }
 componentDidMount() {
    this.props.setClick(this.getAlert);
 }
 getAlert() {
    alert('clicked');
 }
 render() {
  return (
    <h1 ref="hello">Hello</h1>
  );
 }
}

clickChildजब बच्चे को माउंट किया जाता है तो वह माता-पिता की विधि निर्धारित करता है । इस तरह जब आप पैरेंट में बटन पर क्लिक करेंगे तो यह कॉल करेगा clickChildजो बच्चे को कॉल करता है getAlert

यह भी काम करता है यदि आपका बच्चा लिपटे हुए है connect()तो आपको getWrappedInstance()हैक की आवश्यकता नहीं है ।

ध्यान दें कि आप onClick={this.clickChild}माता-पिता में उपयोग नहीं कर सकते हैं क्योंकि जब माता-पिता को बच्चा दिया जाता है तो उसे माउंट नहीं किया जाता है, इसलिए this.clickChildअभी तक असाइन नहीं किया गया है। उपयोग करना onClick={() => this.clickChild()}ठीक है क्योंकि जब आप बटन पर क्लिक करते हैं तो this.clickChildपहले से ही असाइन किया जाना चाहिए।


5
मुझे _this2.clickChild is not a functionक्यों मिलता है?
8

1
इसने मेरे लिए काम नहीं किया: github.com/kriasoft/react-starter-kit/issues/…
tatsu

5
न काम किया। केवल इस उत्तर ने काम किया: github.com/kriasoft/react-starter-kit/issues/…
tatsu

2
यह एक दिलचस्प तकनीक है। यह काफी साफ है और किसी भी नियम को तोड़ता नहीं दिख रहा है। लेकिन मुझे लगता है कि यदि आप एक बंधन जोड़ते हैं तो आपका उत्तर अधिक पूर्ण होगा (और अपेक्षाएं पूरी करेगा)। मुझे इसका उत्तर पसंद आया इसलिए मैंने इसे संबंधित गितुब मुद्दे पर पोस्ट किया है ।
joeytwiddle

7
इसका स्पष्ट जवाब होना चाहिए
यीशु गोमेज़

27

अधिक जवाब के लिए https://facebook.github.io/react/tips/expose-component-functions.html यहाँ पर प्रतिक्रिया करने के तरीके कॉल करें।

"कारण" घटक के रेफ्स को देखकर, आप इनकैप्सुलेशन को तोड़ रहे हैं और उस घटक को ध्यान से पढ़े बिना असंभव बना रहे हैं, जिसका उपयोग किए गए सभी स्थानों की सावधानीपूर्वक जांच करें। इस वजह से, हम दृढ़ता से एक घटक के लिए निजी के रूप में refs के इलाज की सलाह देते हैं, बहुत कुछ राज्य की तरह।

सामान्य तौर पर, डेटा को सहारा के माध्यम से पेड़ के नीचे पारित किया जाना चाहिए। इसके कुछ अपवाद हैं (जैसे कि कॉलिंग .focus) () या एक बार के एनीमेशन को ट्रिगर करना जो वास्तव में "स्थिति" को "परिवर्तित" नहीं करता है, लेकिन किसी भी समय आप "सेट" नामक एक विधि को उजागर कर रहे हैं, प्रॉप्स आमतौर पर होते हैं एक बेहतर विकल्प। इसे बनाने की कोशिश करें ताकि आंतरिक इनपुट घटक इसके आकार और उपस्थिति के बारे में चिंतित हो ताकि इसके पूर्वजों में से कोई भी ऐसा न करे।


5
यहाँ इस जवाब का स्रोत है: चर्चा करें ।reactjs.org / t/… । दूसरों का हवाला देते हुए कोई समस्या नहीं है, लेकिन कम से कम कुछ संदर्भ में रखें।
जोडो

1
यह वास्तव में प्रॉप्स की तुलना में किसी भी तरह से कैसे टूटता है?
टिम्मम

15

उपयोग विधि के साथ वैकल्पिक विधि:

जनक:

const [refresh, doRefresh] = useState(0);
<Button onClick={()=>doRefresh(refresh+1)} />
<Children refresh={refresh} />

बच्चे:

useEffect(() => {
    refresh(); //children function of interest
  }, [props.refresh]);

2
इसे अधिक वोट मिलना चाहिए
अली अल अमाइन

Ps। यदि आपकी इच्छा केवल फॉर्म को फिर से प्रस्तुत करने की है (उदाहरण के लिए, इनपुट फ़ील्ड को रीसेट करने के लिए) तो आपको उपयोग को शामिल करने की भी आवश्यकता नहीं है, आप बस उस घटक को घटक परिवर्तन में भेजे जा रहे प्रोप को बना सकते हैं
मैट फ्लेचर

8

हम एक और तरीके से रेफरी का उपयोग कर सकते हैं-

हम एक मूल तत्व बनाने जा रहे हैं, यह एक <Child/>घटक प्रदान करेगा । जैसा कि आप देख सकते हैं, जो घटक प्रदान किया जाएगा, आपको रेफरी विशेषता को जोड़ने और इसके लिए एक नाम प्रदान करने की आवश्यकता है।
फिर, triggerChildAlertपैरेंट क्लास में स्थित फंक्शन इस संदर्भ के रेफ्स प्रॉपर्टी को एक्सेस करेगा (जब triggerChildAlertफंक्शन ट्रिगर हो जाता है तो चाइल्ड रेफरेंस एक्सेस करेगा और इसमें चाइल्ड एलिमेंट के सभी फंक्शन होंगे)।

class Parent extends React.Component {
    triggerChildAlert(){
        this.refs.child.callChildMethod();
        // to get child parent returned  value-
        // this.value = this.refs.child.callChildMethod();
        // alert('Returned value- '+this.value);
    }

    render() {
        return (
            <div>
                {/* Note that you need to give a value to the ref parameter, in this case child*/}
                <Child ref="child" />
                <button onClick={this.triggerChildAlert}>Click</button>
            </div>
        );
    }
}  

अब, बाल घटक, जैसा कि सैद्धांतिक रूप से पहले डिज़ाइन किया गया था, जैसा दिखेगा:

class Child extends React.Component {
    callChildMethod() {
        alert('Hello World');
        // to return some value
        // return this.state.someValue;
    }

    render() {
        return (
            <h1>Hello</h1>
        );
    }
}

यहाँ स्रोत कोड है-
आशा है कि आपकी मदद करेगा!


1
स्ट्रिंग रेफरी पदावनत हैं। reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
Cory McAboy

4

यदि आप ऐसा केवल इसलिए कर रहे हैं क्योंकि आप चाहते हैं कि बच्चा अपने माता-पिता को पुन: प्रयोज्य विशेषता प्रदान करे, तो आप ऐसा करने पर विचार कर सकते हैं कि इसके बजाय रेंडर-प्रॉप्स का उपयोग किया जाए।

वह तकनीक वास्तव में संरचना को उल्टा कर देती है। Childअब, माता पिता लपेटता तो मैं यह करने के लिए नया नाम दिया है AlertTraitनीचे। मैंने Parentनिरंतरता के लिए नाम रखा , हालांकि यह वास्तव में अब माता-पिता नहीं है।

// Use it like this:

  <AlertTrait renderComponent={Parent}/>


class AlertTrait extends Component {
  // You may need to bind this function, if it is stateful
  doAlert() {
    alert('clicked');
  }
  render() {
    return this.props.renderComponent(this.doAlert);
  }
}

class Parent extends Component {
  render() {
    return (
      <button onClick={this.props.doAlert}>Click</button>
    );
  }
}

इस मामले में, AlertTrait एक या एक से अधिक लक्षण प्रदान करता है, जो इसे उसके renderComponentप्रस्ताव में दिए गए घटक के रूप में सहारा के रूप में गुजरता है ।

जनक doAlertएक प्रस्ताव के रूप में प्राप्त करता है , और जरूरत पड़ने पर इसे कॉल कर सकता है।

(स्पष्टता के लिए, मैंने renderComponentउपर्युक्त उदाहरण में प्रोप को बुलाया । लेकिन ऊपर दिए गए रिएक्ट डॉक्स में, वे इसे कहते हैं render।)

Trait घटक अपने रेंडर फंक्शन में पेरेंट के आसपास के सामान को रेंडर कर सकता है, लेकिन यह पेरेंट के अंदर कुछ भी रेंडर नहीं करता है। वास्तव में यह माता-पिता के अंदर चीजों को प्रस्तुत कर सकता है, अगर यह माता-पिता के लिए एक और प्रस्ताव (जैसे renderChild) पारित करता है, जिसे माता-पिता तब अपनी रेंडर विधि के दौरान उपयोग कर सकते हैं।

यह कुछ हद तक अलग है जो ओपी ने पूछा था, लेकिन कुछ लोग यहां समाप्त हो सकते हैं (जैसे हमने किया) क्योंकि वे एक पुन: प्रयोज्य लक्षण बनाना चाहते थे, और उन्होंने सोचा कि एक बच्चा घटक ऐसा करने का एक अच्छा तरीका था।


यहाँ पुन: प्रयोग करने योग्य लक्षण बनाने के लिए पैटर्न की एक आसान सूची है: reactjs.org/blog/2016/07/13/…
joeytwiddle

क्या होगा अगर आपके पास एन स्टॉपवॉच है और उन सभी को पुनः आरंभ करने के लिए एक बटन है। कैसे यहाँ सहारा सौंपनेवाला काम करता है?
vsync

@vsync मुझे यकीन नहीं है कि यह विधि आपके कार्य के लिए मदद कर सकती है। लेकिन ब्रिकिंगअप का जवाब मदद कर सकता है। ध्यान दें कि वे सेट करते हैं, this.clickChild = clickलेकिन आपके कई स्टॉपवॉच कई कार्यों को पारित करेंगे, इसलिए आपको उन सभी को संग्रहीत करने की आवश्यकता होगी:this.watchRestartFuncs[watchId] = restartWatch
joeytwield

1

आप इसे इस तरह आसानी से हासिल कर सकते हैं

कदम-

  1. मूल श्रेणी में राज्य में बूलियन चर बनाएं। जब आप किसी फ़ंक्शन को कॉल करना चाहते हैं, तो इसे अपडेट करें।
  2. एक प्रोप चर बनाएँ और बूलियन चर असाइन करें।
  3. चाइल्ड कंपोनेंट से उस वेरिएबल को प्रॉपर का उपयोग करते हुए और यदि आप एक शर्त रखते हैं, तो उस विधि को निष्पादित करें।

    class Child extends Component {
       Method=()=>{
       --Your method body--
       }
       render() {
         return (
        //check whether the variable has been updated or not
          if(this.props.updateMethod){
            this.Method();
          }
         )
       }
    }
    
    class Parent extends Component {
    
    constructor(){
      this.state={
       callMethod:false
      }
    
    }
    render() {
       return (
    
         //update state according to your requirement
         this.setState({
            callMethod:true
         }}
         <Child updateMethod={this.state.callMethod}></Child>
        );
       }
    }

आप इसे सैंडबॉक्स करना चाह सकते हैं। ऐसा लगता है कि आप एक अनंत लूप के साथ समाप्त होने जा रहे हैं क्योंकि बाल विधि लगातार चलेगी क्योंकि माता-पिता की स्थिति सच है।
इसहाक पाक

@IsaacPak हाँ, इसीलिए मैंने एक टिप्पणी छोड़ दी, जिसमें कहा गया था कि आपको अपनी आवश्यकता के अनुसार राज्य को अपडेट करना होगा। तब यह अनंत लूप के रूप में नहीं चलेगा।
कुसल किथमल

1

मैं useEffectयह सब करने के सिरदर्द को दूर करने के लिए हुक का उपयोग कर रहा हूं इसलिए अब मैं इस तरह से बच्चे को नीचे एक चर देता हूं:

<ParentComponent>
 <ChildComponent arbitrary={value} />
</ParentComponent>
useEffect(() => callTheFunctionToBeCalled(value) , [value]);

1

मैं यहाँ प्रस्तुत किसी भी समाधान से संतुष्ट नहीं था। वास्तव में एक बहुत ही सरल समाधान है जो मूल जावास्क्रिप्ट ऑब्जेक्ट के अलावा कुछ रिएक्ट कार्यक्षमता पर निर्भर किए बिना शुद्ध जावास्क्रिप्ट का उपयोग करके किया जा सकता है - और यह आपको या तो दिशा में संवाद करने का लाभ देता है (माता-पिता -> बच्चा, बच्चा -> माता-पिता)। आपको पैरेंट कंपोनेंट से चाइल्ड कंपोनेंट तक कोई ऑब्जेक्ट पास करना होगा। यह वस्तु वह है जिसे मैं "द्वि-दिशात्मक संदर्भ" या संक्षिप्त रूप में संक्षिप्त करता हूं। मूल रूप से, ऑब्जेक्ट में माता-पिता के तरीकों का संदर्भ होता है जिसे माता-पिता उजागर करना चाहते हैं। और चाइल्ड कंपोनेंट उस ऑब्जेक्ट को मेथड्स अटैच करता है जिसे पेरेंट कॉल कर सकते हैं। कुछ इस तरह:

// Parent component.
function MyParentComponent(props) {

   function someParentFunction() {
      // The child component can call this function.
   }

   function onButtonClick() {
       // Call the function inside the child component.
       biRef.someChildFunction();
   }

   // Add all the functions here that the child can call.
   var biRef = {
      someParentFunction: someParentFunction
   }

   return <div>
       <MyChildComponent biRef={biRef} />
       <Button onClick={onButtonClick} />
   </div>;
}


// Child component
function MyChildComponent(props) {

   function someChildFunction() {
      // The parent component can call this function.
   }


   function onButtonClick() {
      // Call the parent function.
      props.biRef.someParentFunction();
   }

   // Add all the child functions to props.biRef that you want the parent
   // to be able to call.
   props.biRef.someChildFunction = someChildFunction;

   return <div>
       <Button onClick={onButtonClick} />
   </div>;
}

इस समाधान का दूसरा लाभ यह है कि आप माता-पिता और बच्चे में बहुत अधिक कार्य जोड़ सकते हैं, जबकि माता-पिता से बच्चे को केवल एक ही संपत्ति का उपयोग करके उन्हें पारित कर सकते हैं।

ऊपर दिए गए कोड में सुधार करने के लिए माता-पिता और बच्चे के कार्यों को सीधे biRef ऑब्जेक्ट में नहीं जोड़ना है, बल्कि उप सदस्यों के लिए है। माता-पिता के कार्यों को "माता-पिता" नामक एक सदस्य में जोड़ा जाना चाहिए, जबकि बच्चे के कार्यों को "बच्चे" नामक सदस्य में जोड़ा जाना चाहिए।

// Parent component.
function MyParentComponent(props) {

   function someParentFunction() {
      // The child component can call this function.
   }

   function onButtonClick() {
       // Call the function inside the child component.
       biRef.child.someChildFunction();
   }

   // Add all the functions here that the child can call.
   var biRef = {
      parent: {
          someParentFunction: someParentFunction
      }
   }

   return <div>
       <MyChildComponent biRef={biRef} />
       <Button onClick={onButtonClick} />
   </div>;
}


// Child component
function MyChildComponent(props) {

   function someChildFunction() {
      // The parent component can call this function.
   }


   function onButtonClick() {
      // Call the parent function.
      props.biRef.parent.someParentFunction();
   }

   // Add all the child functions to props.biRef that you want the parent
   // to be able to call.
   props.biRef {
       child: {
            someChildFunction: someChildFunction
       }
   }

   return <div>
       <Button onClick={onButtonClick} />
   </div>;
}

माता-पिता और बच्चे के कार्यों को biRef ऑब्जेक्ट के अलग-अलग सदस्यों में रखकर, आप दोनों के बीच एक स्वच्छ अलगाव होगा और आसानी से देख पाएंगे कि कौन से माता-पिता या बच्चे से संबंधित हैं। यदि यह एक ही फ़ंक्शन दोनों में दिखाई देता है, तो यह गलती से एक बच्चे के घटक को मूल फ़ंक्शन को ओवरराइट करने से रोकने में मदद करता है।

एक अंतिम बात यह है कि यदि आप ध्यान दें, तो मूल घटक var के साथ biRef ऑब्जेक्ट बनाता है जबकि चाइल्ड घटक इसे props ऑब्जेक्ट के माध्यम से एक्सेस करता है। यह माता-पिता में biRef ऑब्जेक्ट को परिभाषित नहीं करने और अपने स्वयं के प्रॉपर पैरामीटर (जो UI तत्वों के पदानुक्रम में मामला हो सकता है) के माध्यम से अपने माता-पिता से इसे एक्सेस करने के लिए लुभावना हो सकता है। यह जोखिम भरा है क्योंकि बच्चा सोच सकता है कि यह एक समारोह है जिसे वह माता-पिता के पास बुला रहा है, जब वह वास्तव में दादा-दादी से संबंधित हो। जब तक आप इसके बारे में जानते हैं तब तक इसमें कुछ भी गलत नहीं है। जब तक आपके पास माता-पिता / बच्चे के रिश्ते से परे कुछ पदानुक्रम का समर्थन करने का कोई कारण नहीं है, तब तक अपने माता-पिता के घटक में biRef बनाना सबसे अच्छा है।


0

आप इनहेरिटेंस इनवर्जन कर सकते हैं (इसे यहां देखें: https://medium.com/@franleplant/react-higher-order-compenders-in-depth-cf9032ee6c3e )। इस तरह आपके पास उस घटक के उदाहरण तक पहुंच है जिसे आप लपेटेंगे (इस प्रकार आप इसे उपयोग करने में सक्षम होंगे)


0

मुझे लगता है कि तरीकों को कॉल करने का सबसे बुनियादी तरीका बाल घटक पर एक अनुरोध स्थापित करना है। फिर जैसे ही बच्चा अनुरोध को संभालता है, यह अनुरोध को रीसेट करने के लिए कॉलबैक विधि कहता है।

रीसेट तंत्र एक-दूसरे के बाद एक ही अनुरोध को कई बार भेजने में सक्षम होना आवश्यक है।

मूल घटक में

माता-पिता की रेंडर विधि में:

const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);

माता-पिता को 2 दिशाओं में अपने बच्चे के साथ संवाद करने के लिए 2 तरीकों की आवश्यकता होती है।

sendRequest() {
  const request = { param: "value" };
  this.setState({ request });
}

resetRequest() {
  const request = null;
  this.setState({ request });
}

बाल घटक में

बच्चा अपनी आंतरिक स्थिति को अपडेट करता है, और प्रॉप्स से अनुरोध की प्रतिलिपि बनाता है।

constructor(props) {
  super(props);
  const { request } = props;
  this.state = { request };
}

static getDerivedStateFromProps(props, state) {
  const { request } = props;
  if (request !== state.request ) return { request };
  return null;
}

फिर अंत में यह अनुरोध को संभालता है, और अभिभावक को रीसेट भेजता है:

componentDidMount() {
  const { request } = this.state;
  // todo handle request.

  const { onRequestHandled } = this.props;
  if (onRequestHandled != null) onRequestHandled();
}

0

माता-पिता से बच्चे के कार्य को शुरू करने का एक अन्य तरीका componentDidUpdateबाल घटक में फ़ंक्शन का उपयोग करना है । मैं triggerChildFuncपेरेंट से चाइल्ड के लिए एक प्रॉप पास करता हूं , जो शुरू में है null। जब बटन पर क्लिक किया जाता है और चाइल्ड नोटिस componentDidUpdateअपने स्वयं के आंतरिक फ़ंक्शन को बदलता है और कॉल करता है, तो फ़ंक्शन एक फ़ंक्शन में बदल जाता है ।

चूंकि triggerChildFuncकिसी फ़ंक्शन में परिवर्तन होता है, इसलिए हमें अभिभावक को कॉलबैक भी मिलता है। यदि माता-पिता को यह जानने की आवश्यकता नहीं है कि फ़ंक्शन को कहा जाता है, तो triggerChildFuncउदाहरण के बदले मान बदले nullजा trueसकता है।

const { Component } = React;
const { render } = ReactDOM;

class Parent extends Component {
  state = {
    triggerFunc: null
  }

  render() {
    return (
      <div>
        <Child triggerChildFunc={this.state.triggerFunc} />
        <button onClick={() => {
          this.setState({ triggerFunc: () => alert('Callback in parent')})
        }}>Click
        </button>
      </div>
    );
  }
}

class Child extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.triggerChildFunc !== prevProps.triggerChildFunc) {
      this.onParentTrigger();
    }
  }

  onParentTrigger() {
    alert('parent triggered me');

    // Let's call the passed variable from parent if it's a function
    if (this.props.triggerChildFunc && {}.toString.call(this.props.triggerChildFunc) === '[object Function]') {
      this.props.triggerChildFunc();
    }
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}


render(
  <Parent />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='app'></div>

CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010


0

यहाँ मेरा डेमो: https://stackblitz.com/edit/react-dgz1ee?file=styles.css

मैं useEffectबच्चों को घटक के तरीकों को कॉल करने के लिए उपयोग कर रहा हूं । मैंने कोशिश की है Proxy and Setter_Getterलेकिन useEffectमाता-पिता से एक बच्चे की पद्धति को कॉल करने के लिए अधिक सुविधाजनक तरीका लगता है। इसका उपयोग करने के लिए Proxy and Setter_Getterऐसा लगता है कि पहले पर काबू पाने के लिए कुछ सूक्ष्मता है, क्योंकि पहले प्रदान किया गया तत्व एक वस्तु का तत्व है जो ref.current return => <div/>'विशिष्टता' के माध्यम से है । विषय मेंuseEffect , आप भी माता-पिता के राज्य क्या आप बच्चों के साथ क्या करना चाहते हैं पर निर्भर करता है स्थापित करने के लिए इस दृष्टिकोण पर लाभ उठा सकते हैं।

मेरे द्वारा प्रदत्त डेमो लिंक में, आपको मेरे ड्राफ्टवर्क के साथ मेरा पूरा रिएक्टजेएस कोड मिलेगा, ताकि आप मेरे समाधान के वर्कफ़्लो की सराहना कर सकें।

यहां मैं आपको केवल संबंधित कोड के साथ अपना रिएक्टजस स्निपेट प्रदान कर रहा हूं। :

import React, {
  Component,
  createRef,
  forwardRef,
  useState,
  useEffect
} from "react"; 

{...}

// Child component
// I am defining here a forwardRef's element to get the Child's methods from the parent
// through the ref's element.
let Child = forwardRef((props, ref) => {
  // I am fetching the parent's method here
  // that allows me to connect the parent and the child's components
  let { validateChildren } = props;
  // I am initializing the state of the children
  // good if we can even leverage on the functional children's state
  let initialState = {
    one: "hello world",
    two: () => {
      console.log("I am accessing child method from parent :].");
      return "child method achieve";
    }
  };
  // useState initialization
  const [componentState, setComponentState] = useState(initialState);
  // useEffect will allow me to communicate with the parent
  // through a lifecycle data flow
  useEffect(() => {
    ref.current = { componentState };
    validateChildren(ref.current.componentState.two);
  });

{...}

});

{...}

// Parent component
class App extends Component {
  // initialize the ref inside the constructor element
  constructor(props) {
    super(props);
    this.childRef = createRef();
  }

  // I am implementing a parent's method
  // in child useEffect's method
  validateChildren = childrenMethod => {
    // access children method from parent
    childrenMethod();
    // or signaling children is ready
    console.log("children active");
  };

{...}
render(){
       return (
          {
            // I am referencing the children
            // also I am implementing the parent logic connector's function
            // in the child, here => this.validateChildren's function
          }
          <Child ref={this.childRef} validateChildren={this.validateChildren} />
        </div>
       )
}

0

हम कस्टम हुक से खुश हैं जिसे हम कहते हैं useCounterKey। यह बस एक काउंटरकी, या एक कुंजी सेट करता है जो शून्य से गिना जाता है। यह जो फ़ंक्शन देता है वह कुंजी (यानी वेतन वृद्धि) को रीसेट करता है। (मेरा मानना ​​है कि यह रिएक्ट में सबसे मुहावरेदार तरीका है एक घटक को रीसेट करने के लिए - बस कुंजी को टक्कर दें।)

हालाँकि यह हुक किसी भी स्थिति में काम करता है जहाँ आप क्लाइंट को कुछ करने के लिए एक बार संदेश भेजना चाहते हैं। उदाहरण के लिए, हम एक निश्चित मूल घटना पर बच्चे में नियंत्रण को केंद्रित करने के लिए इसका उपयोग करते हैं - यह कुंजी को अद्यतन किए जाने पर कभी भी ऑटोफोकस करता है। (यदि अधिक प्रॉप्स की आवश्यकता होती है, तो वे कुंजी को रीसेट करने से पहले सेट किया जा सकता है ताकि घटना होने पर वे उपलब्ध हों।)

इस पद्धति का एक सा सीखने की अवस्था है b / c यह एक विशिष्ट ईवेंट हैंडलर की तरह सीधा नहीं है, लेकिन इसे रिएक्ट में इसे संभालने के लिए सबसे मुहावरेदार तरीका लगता है जो हमने पाया है (क्योंकि चाबियाँ पहले से ही इस तरह से काम करती हैं)। इस विधि पर प्रतिक्रिया के लिए खुले रहो लेकिन यह अच्छी तरह से काम कर रहा है!

// Main helper hook:
export function useCounterKey() {
  const [key, setKey] = useState(0);
  return [key, () => setKey(prev => prev + 1)] as const;
}

नमूना उपयोग:

// Sample 1 - normal React, just reset a control by changing Key on demand
function Sample1() {
  const [inputLineCounterKey, resetInputLine] = useCounterKey();

  return <>
    <InputLine key={inputLineCounterKey} />
    <button onClick={() => resetInputLine()} />
  <>;
}

// Second sample - anytime the counterKey is incremented, child calls focus() on the input
function Sample2() {
  const [amountFocusCounterKey, focusAmountInput] = useCounterKey();

  // ... call focusAmountInput in some hook or event handler as needed

  return <WorkoutAmountInput focusCounterKey={amountFocusCounterKey} />
}

function WorkoutAmountInput(props) {
  useEffect(() => {
    if (counterKey > 0) {
      // Don't focus initially
      focusAmount();
    }
  }, [counterKey]);

  // ...
}

( काउंटरक अवधारणा के लिए केंट डॉड्स को श्रेय ।)


-1

यहाँ एक बग है? के लिए बाहर देखने के लिए: मैं आगे का उपयोग कर rossipedia के समाधान के साथ कॉन्करर, useRef, useIperativeHandle

ऑनलाइन कुछ गलत जानकारी है जो कहती है कि केवल रिएक्ट क्लास के घटकों से ही refs बनाए जा सकते हैं, लेकिन यदि आप ऊपर दिए गए हुक का उपयोग करते हैं तो आप वास्तव में फ़ंक्शन घटकों का उपयोग कर सकते हैं। एक नोट, हुक ने केवल मेरे लिए काम किया जब मैंने घटक को निर्यात करने के दौरान फाइल को withRouter () का उपयोग नहीं करने के लिए बदल दिया। यानी से एक बदलाव

export default withRouter(TableConfig);

इसके बजाय हो

export default TableConfig;

इस तरह के एक घटक के लिए hindight () की जरूरत नहीं है, लेकिन आमतौर पर इसमें कुछ भी चोट नहीं लगती है। मेरा उपयोग मामला यह है कि मैंने कॉन्फ़िगरेशन मानों के देखने और संपादन को संभालने के लिए एक तालिका बनाने के लिए एक घटक बनाया है। और मैं चाहता था कि जब भी पैरेंट फॉर्म का रीसेट बटन हिट हो, तो यह इस चाइल्ड कंपोनेंट को रीसेट करने के लिए सक्षम हो। जब तक मैं अपने बच्चे के घटक TableConfig वाली फ़ाइल से withRouter () को हटा नहीं देता तब तक UseRef () को ठीक से रेफरी या Ref.current नहीं मिलेगा (अशक्त रहने पर)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.