외부에서 React 컴포넌트 메소드 호출


95

React Element의 인스턴스에서 React 컴포넌트에 의해 노출 된 메서드를 호출하고 싶습니다.

예를 들어,이 jsfiddle . 참조 에서 alertMessage메서드 를 호출하고 싶습니다 HelloElement.

추가 래퍼를 작성하지 않고도이를 달성 할 수있는 방법이 있습니까?

편집 (JSFiddle에서 복사 한 코드)

<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은 하향 투표를 보장하지 않을만큼 일반적입니다.
제프 Fairley

그런 일을 보증하는 유스 케이스가 무엇인지 궁금합니다. 이것은 응용 프로그램 imo를 디자인하는 좋은 방법이 아닙니다. 무언가를 재사용해야하는 경우 세 번째 파일에 별도의 공통 도우미를 만들어 버튼 및 반응 구성 요소에 사용하십시오.
.01.21

답변:


56

내부 함수에 액세스하는 방법에는 두 가지가 있습니다. 하나, 인스턴스 수준, 원하는대로 다른 정적 수준.

에서 반환 할 때 함수를 호출해야합니다 React.render. 아래를 참조하십시오.

공전

ReactJS Statics를 살펴보십시오 . 단, 정적 기능을하지 액세스 인스턴스 레벨 데이터는 그렇게 할 수 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
render의 반환 값을 사용하는 것은 더 이상 사용되지 않는 것으로 간주되며 성능 향상을 위해 향후 버전에서 제거 될 예정입니다. 구성 요소 인스턴스 개체에 대한 참조를 가져 오는 지원되는 방법은 ref인스턴스를 매개 변수로 사용하여 호출되는 함수 인 속성을 추가하는 것 입니다. 이것은 또한 최상위 수준에 있지 않은 객체에 액세스 할 수있게 해줍니다. 예를 들어 렌더링하는 경우 함수에 <MuiThemeProvider><Hello ref={setHelloRef} /></MuiThemeProvider>전달되는 참조 setHelloRefMuiThemeProvider.
Periata Breatta 2016 년

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
사실, 간단하고 기능적입니다! 당연한 것처럼. 나는 그것이 얼마나 단순한 지에 대해 매우 감명 받았다. 정말 생각하지 않았습니다. 아마도 더 많은 구성 요소가 필요한 경우이 접근 방식은 그렇게 잘 작동하지 않을 것입니다. 감사합니다!
Leonardo Maffei

6
전역 변수를 추가하는 것은 좋은 해결책이 아닙니다. 전역 변수가 왜 나쁜지에 대한 자세한 내용은 wiki.c2.com/?GlobalVariablesAreBad
Salvatore Zappalà

3
투표 해주셔서 감사합니다 !! 예 전역 변수는 좋지 않지만 문제를 해결하는 방법입니다.
Kushal Jain 2018

이것이 제가 필요로하는 실용적이고 간단한 솔루션입니다. 감사합니다!
Florent Destremau 2019 년

2
작동했지만 동일한 페이지에 동일한 구성 요소가 여러 개 있으면 작동하지 않습니다.
gaurav

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');
    }

}

나는이 정확한 코드를 테스트하지 않았지만 이것은 내가 내 프로젝트에서 한 일과 잘 어울립니다. :). 물론 이것은 나쁜 예입니다. props를 사용해야하지만 제 경우에는 하위 구성 요소가 해당 구성 요소 내부에 유지하려는 API 호출을 수행했습니다. 그러한 경우 이것은 좋은 해결책입니다.


5
제 생각에는this.cowCallbacks.say('moo')
Steven

BTW this대신 콜백 (Cow의 인스턴스가 될) 에 전달할 수 있습니다 callbacks.
WebBrother 2019

예 @WebBrother,하지만 훨씬 더 해키 것
gitaarik

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();
빌 Dagg

내 이전 의견에 더 나아가 ... 또는 더 나은 방법은 구성 요소의 alertMessage 메서드를 상태로 설정하는 것입니다.
Bill Dagg

내가 이것을 시도하면 나는 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?창에 구성 요소를 바인딩하지 않습니다
Guerrilla

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

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

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

를 사용하여 창에서이 메서드를 호출 할 수 있습니다 window.alertMessage().


이것은 작동하지만 전역 변수를 추가하는 것은 여러 가지 이유로 좋은 해결책이 아닙니다. 전역 변수가 왜 나쁜지에 대한 자세한 정보는 여기에서 찾을 수 있습니다. wiki.c2.com/?GlobalVariablesAreBad
Salvatore Zappalà

3

ES6에있는 경우 예제의 메서드에 "static"키워드를 사용하면 다음과 같습니다. static alertMessage: function() { ...
},

희망은 누구든지 도울 수 있습니다 :)


정적 함수에서는 props 또는 state에 도달 할 수 없습니다.
세르 다르 데 기르 멘치 (Değirmenci)

예,하지만 질문은 alertMessage () 함수에 액세스하려고 했으므로 HelloElement.alertMessage ()를 사용할 수 있습니다.
darmis

일반적으로 props와 state를 사용하지 않고 함수를 호출하는 것은 효과가 없습니다. 당신이 바로에 대한 기능을 도달하고 그러나, 나는 내 투표를 제거하고
세르 다르 데 기르 멘치 (Değirmenci)

2

onClick함수 ( onClickReact의 자체 구현 onClick) 를 사용하여 div에 핸들러를 추가하고 { }중괄호로 속성에 액세스 할 수 있으며 경고 메시지가 나타납니다.

컴포넌트 클래스에서 호출 할 수있는 정적 메소드를 정의하려면 정적을 사용해야합니다. 이기는 하지만:

"이 블록 내에서 정의 된 메서드는 정적입니다. 즉, 구성 요소 인스턴스가 생성되기 전에 실행할 수 있으며 메서드는 구성 요소의 상태 또는 소품에 액세스 할 수 없습니다. 정적에서 소품의 값을 확인하려는 경우 메서드의 경우 호출자가 정적 메서드에 대한 인수로 props를 전달하도록합니다. " ( 출처 )

몇 가지 예제 코드 :

    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

방법 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은 자식 구성 요소 메서드에 액세스하는 매우 쉽고 깔끔한 방법입니다. 감사!
gabdara 19

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);
        });
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.