बाहर से एक प्रतिक्रिया घटक विधि को बुलाओ


95

मैं एक घटक को एक प्रतिक्रिया तत्व के उदाहरण से एक प्रतिक्रिया घटक द्वारा उजागर करना चाहता हूं।

उदाहरण के लिए, इस jsfiddle में । मैं संदर्भ alertMessageसे विधि को कॉल करना चाहता हूं HelloElement

क्या अतिरिक्त रैपर लिखने के बिना इसे प्राप्त करने का एक तरीका है?

संपादित करें (JSField से कॉपी किया गया कोड)

<div id="container"></div>
<button onclick="onButtonClick()">Click me!</button>
var onButtonClick = function () {

    //call alertMessage method from the reference of a React Element! Something like HelloElement.alertMessage()
    console.log("clicked!");
}

var Hello = React.createClass({displayName: 'Hello',

    alertMessage: function() {
        alert(this.props.name);                             
    },

    render: function() {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

var HelloElement = React.createElement(Hello, {name: "World"});

React.render(
    HelloElement,
    document.getElementById('container')
);

3
आदर्श नहीं है, लेकिन JSFiddle पर्याप्त है कि यह एक डाउन वोट वारंट नहीं करता है।
जेफ फेयरली

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

जवाबों:


56

एक आंतरिक फ़ंक्शन तक पहुंचने के दो तरीके हैं। एक, उदाहरण-स्तर, जैसे आप चाहते हैं, दूसरा, स्थैतिक स्तर।

उदाहरण

आपको रिटर्न से फ़ंक्शन को कॉल करने की आवश्यकता है React.render। निचे देखो।

स्थिर

ReactJS स्टैटिक्स पर एक नज़र । हालाँकि, ध्यान दें कि एक स्थिर फ़ंक्शन इंस्टेंस-स्तर डेटा तक नहीं पहुंच thisसकता है , इसलिए यह होगा undefined

var onButtonClick = function () {
    //call alertMessage method from the reference of a React Element! 
    HelloRendered.alertMessage();
    //call static alertMessage method from the reference of a React Class! 
    Hello.alertMessage();
    console.log("clicked!");
}

var Hello = React.createClass({
    displayName: 'Hello',
    statics: {
        alertMessage: function () {
            alert('static message');
        }
    },
    alertMessage: function () {
        alert(this.props.name);
    },

    render: function () {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

var HelloElement = React.createElement(Hello, {
    name: "World"
});

var HelloRendered = React.render(HelloElement, document.getElementById('container'));

फिर करते हैं HelloRendered.alertMessage()


13
ध्यान दें कि रेंडर के रिटर्न वैल्यू का उपयोग करने वाले को पदावनत माना जाता है, और भविष्य के संस्करणों में प्रदर्शन संवर्द्धन को सक्षम करने के लिए हटाए जाने की उम्मीद की जाती है। अपने घटक उदाहरण ऑब्जेक्ट के लिए संदर्भ प्राप्त करने का समर्थित तरीका एक संपत्ति जोड़ना है refजो एक फ़ंक्शन है जिसे उदाहरण के लिए पैरामीटर के रूप में कहा जाता है। यह आपको उन वस्तुओं तक पहुंचने की अनुमति देता है जो शीर्ष स्तर पर नहीं हैं, उदाहरण के लिए, यदि आप प्रदान <MuiThemeProvider><Hello ref={setHelloRef} /></MuiThemeProvider>कर रहे हैं तो आपको setHelloRefएक से अधिक के बजाय अपने फ़ंक्शन को दिया गया सही संदर्भ मिलेगा MuiThemeProvider
पेरियाटा ब्रीटा

44

आप पसंद कर सकते हैं

import React from 'react';

class Header extends React.Component{

    constructor(){
        super();
        window.helloComponent = this;
    }

    alertMessage(){
       console.log("Called from outside");
    }

    render(){

      return (
      <AppBar style={{background:'#000'}}>
        Hello
      </AppBar>
      )
    }
}

export default Header;

अब इस घटक के बाहर से आप नीचे इस तरह कह सकते हैं

window.helloComponent.alertMessage();

1
वास्तव में, सरल और कार्यात्मक! जैसा माना जाता है। मैं इस बात से बहुत प्रभावित हूँ कि यह कितना सरल है; वास्तव में नहीं सोचा था। संभवतः यह दृष्टिकोण उस अच्छे से काम नहीं करेगा यदि आपके पास अधिक से अधिक घटक हों। धन्यवाद!
लियोनार्डो माफ़ेई

6
एक वैश्विक चर जोड़ना अच्छा समाधान नहीं है। अधिक क्यों वैश्विक चर यहाँ बुरा कर रहे हैं: wiki.c2.com/?GlobalVariablesAreBad
Salvatore

3
वोट के लिए धन्यवाद !! हाँ वैश्विक चर अच्छा नहीं है, लेकिन यह आपकी समस्या को हल करने का एक तरीका है।
कुशाल जैन

यह बिल्कुल व्यावहारिक और सरल समाधान है जिसकी मुझे ज़रूरत थी, धन्यवाद!
फ्लोरेंट डेस्ट्रेमाऊ

2
यह काम किया है, लेकिन यह काम नहीं करेगा यदि आपके पास एक ही पृष्ठ पर एक ही घटक है।
गौरव

26

मैंने कुछ इस तरह किया है:

class Cow extends React.Component {

    constructor (props) {
        super(props);
        this.state = {text: 'hello'};
    }

    componentDidMount () {
        if (this.props.onMounted) {
            this.props.onMounted({
                say: text => this.say(text)
            });
        }
    }

    render () {
        return (
            <pre>
                 ___________________
                < {this.state.text} >
                 -------------------
                        \   ^__^
                         \  (oo)\_______
                            (__)\       )\/\
                                ||----w |
                                ||     ||
            </pre>
        );
    }

    say (text) {
        this.setState({text: text});
    }

}

और फिर कहीं और:

class Pasture extends React.Component {

    render () {
        return (
            <div>
                <Cow onMounted={callbacks => this.cowMounted(callbacks)} />
                <button onClick={() => this.changeCow()} />
            </div>
        );
    }

    cowMounted (callbacks) {
        this.cowCallbacks = callbacks;
    }

    changeCow () {
        this.cowCallbacks.say('moo');
    }

}

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


5
मुझे लगता है कि आपका मतलब थाthis.cowCallbacks.say('moo')
स्टीवन

BTW के thisबजाय कॉलबैक (जो गाय का एक उदाहरण होगा) को पारित करना संभव है callbacks
वेबब्रॉटर

@WebBrother हाँ, लेकिन वह और भी अधिक
हैकिया होगा

6

renderसंभावित रूप से लौटाए गए मूल्य को दर्शाते हुए विधि के साथ , अनुशंसित दृष्टिकोण अब मूल तत्व को कॉलबैक रेफरी संलग्न करना है। इस कदर:

ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));

जिसके बाद हम window.helloComponent का उपयोग करके एक्सेस कर सकते हैं, और इसके किसी भी तरीके को window.helloComponent.METHOD से एक्सेस किया जा सकता है।

यहाँ एक पूर्ण उदाहरण है:

var onButtonClick = function() {
  window.helloComponent.alertMessage();
}

class Hello extends React.Component {
  alertMessage() {
    alert(this.props.name);
  }

  render() {
    return React.createElement("div", null, "Hello ", this.props.name);
  }
};

ReactDOM.render( <Hello name="World" ref={(element) => {window.helloComponent = element}}/>, document.getElementById('container'));
<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="container"></div>
<button onclick="onButtonClick()">Click me!</button>


संदर्भ को खिड़की की वस्तु के बजाय स्थानीय स्थिति में रखने के लिए बेहतर है ... ref={component => {this.setState({ helloComponent: component; })}} फिर, क्लिक हैंडलर में ... this.state.helloComponent.alertMessage();
बिल डग्ग

इसके अलावा मेरी पिछली टिप्पणी के लिए ... या, अभी तक बेहतर, बस घटक चेतावनी अलर्ट विधि राज्य में डाल दिया।
बिल डाग

जब मैं Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?इसे पाने की कोशिश करता हूं और यह घटक को खिड़की से नहीं बांधता है
गुरिल्ला

4
class AppProvider extends Component {
  constructor() {
    super();

    window.alertMessage = this.alertMessage.bind(this);
  }

  alertMessage() {
    console.log('Hello World');
 }
}

आप इस विधि का उपयोग करके विंडो से कॉल कर सकते हैं window.alertMessage()


यह काम करेगा लेकिन एक वैश्विक चर जोड़ना कई कारणों से एक अच्छा समाधान नहीं है। आप वैश्विक चर क्यों यहां खराब हैं के बारे में अधिक जानकारी प्राप्त कर सकते हैं: wiki.c2.com/?GlobalVariablesAreBad
सल्वातोर

3

यदि आप ईएस 6 में हैं तो अपने उदाहरण पर अपनी विधि पर "स्थिर" कीवर्ड का उपयोग करें: static alertMessage: function() { ...
},

आशा है कि वहाँ किसी की मदद कर सकते हैं :)


आप किसी स्थिर फ़ंक्शन में प्रॉप्स या स्थिति तक नहीं पहुँच सकते।
सर्डर Değirmenci

ठीक है हाँ, लेकिन सवाल अलर्टमेसेज () फंक्शन को एक्सेस करने का था ताकि आप HelloElement.alertMessage () का उपयोग कर सकें।
darmis

आमतौर पर प्रॉप्स और राज्य का उपयोग किए बिना किसी फ़ंक्शन को कॉल करने का कोई प्रभाव नहीं पड़ता है। लेकिन जैसा कि आप सही के बारे में समारोह तक पहुंच रहे हैं, मैं अपने वोट को हटाने हूँ
सर्डर Değirmenci

2

आप onClickफ़ंक्शन के साथ div में एक हैंडलर जोड़ सकते हैं ( onClickयह React का अपना कार्यान्वयन है onClick) और आप { }घुंघराले ब्रेसिज़ के भीतर संपत्ति तक पहुंच सकते हैं , और आपका अलर्ट संदेश दिखाई देगा।

मामले में आप स्टैटिक विधियों को परिभाषित करना चाहते हैं जिन्हें घटक वर्ग पर बुलाया जा सकता है - आपको स्टैटिक्स का उपयोग करना चाहिए। हालांकि:

"इस ब्लॉक के भीतर परिभाषित तरीके स्थिर हैं, जिसका अर्थ है कि आप उन्हें किसी भी घटक इंस्टेंसेस के बनने से पहले चला सकते हैं, और विधियों में आपके घटकों की प्रॉप्स या स्थिति तक पहुंच नहीं है। यदि आप स्थैतिक में प्रॉप्स के मूल्य की जांच करना चाहते हैं। विधि, स्थिर विधि के तर्क के रूप में प्रॉपर में कॉलर पास है। " ( स्रोत )

कुछ उदाहरण कोड:

    const Hello = React.createClass({

        /*
            The statics object allows you to define static methods that can be called on the component class. For example:
        */
        statics: {
            customMethod: function(foo) {
              return foo === 'bar';
            }
        },


        alertMessage: function() {
            alert(this.props.name);                             
        },

        render: function () {
            return (
                <div onClick={this.alertMessage}>
                Hello {this.props.name}
                </div>
            );
        }
    });

    React.render(<Hello name={'aworld'} />, document.body);

आशा है कि यह आपकी थोड़ी मदद करता है, क्योंकि मुझे नहीं पता कि क्या मैं आपके प्रश्न को सही ढंग से समझ पाया हूं, इसलिए यदि मैंने इसे गलत समझा तो मुझे सही कर लें :)


2

ऐसा प्रतीत होता है कि स्टैटिक्स पदावनत हो गए हैं, और कुछ कार्यों को उजागर करने के अन्य तरीके renderजटिल प्रतीत होते हैं। इस बीच, स्टैक ओवरफ्लो ने डीबगिंग रिएक्ट के बारे में जवाब दिया , जबकि हैक-वाई लगता है, मेरे लिए काम किया।


2

विधि 1 using ChildRef :

public childRef: any = React.createRef<Hello>();

public onButtonClick= () => {
    console.log(this.childRef.current); // this will have your child reference
}

<Hello ref = { this.childRef }/>
<button onclick="onButtonClick()">Click me!</button>

विधि 2: using window register

public onButtonClick= () => {
    console.log(window.yourRef); // this will have your child reference
}

<Hello ref = { (ref) => {window.yourRef = ref} }/>`
<button onclick="onButtonClick()">Click me!</button>

विधि 1 बाल घटक विधियों तक पहुंचने का एक बहुत आसान और साफ तरीका है। धन्यवाद!
गबरू

2

साथ में React hook - useRef



const MyComponent = ({myRef}) => {
  const handleClick = () => alert('hello world')
  myRef.current.handleClick = handleClick
  return (<button onClick={handleClick}>Original Button</button>)
}

MyComponent.defaultProps = {
  myRef: {current: {}}
}

const MyParentComponent = () => {
  const myRef = React.useRef({})
  return (
    <>
      <MyComponent 
        myRef={myRef}
      />
      <button onClick={myRef.curent.handleClick}>
        Additional Button
      </button>
    </>
  )
}

शुभ लाभ...


1

मैं घटकों को प्रस्तुत करने और एक घटक उदाहरण वापस करने के लिए इस सहायक विधि का उपयोग करता हूं। तरीकों को उस उदाहरण पर बुलाया जा सकता है।

static async renderComponentAt(componentClass, props, parentElementId){
         let componentId = props.id;
        if(!componentId){
            throw Error('Component has no id property. Please include id:"...xyz..." to component properties.');
        }

        let parentElement = document.getElementById(parentElementId);

        return await new Promise((resolve, reject) => {
            props.ref = (component)=>{
                resolve(component);
            };
            let element = React.createElement(componentClass, props, null);
            ReactDOM.render(element, parentElement);
        });
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.