从外部调用 React 组件方法

IT技术 reactjs
2021-04-07 02:08:28

我想从 React Element 的实例调用一个由 React 组件公开的方法。

例如,在这个jsfiddle 中我想alertMessageHelloElement参考中调用该方法

有没有办法在不必编写额外的包装器的情况下实现这一点?

编辑(从 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')
);
6个回答

有两种方法可以访问内部函数。一个,实例级别,如您所愿,另一个,静态级别。

实例

您需要在从 返回时调用该函数React.render见下文。

静止的

看看ReactJS 静态但是请注意,是一个静态函数不能访问实例级别的数据,因此thisundefined

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()

请注意,使用 render 的返回值被视为已弃用,预计将在未来版本中删除以实现性能增强。获取对组件实例对象的引用的支持方法是添加一个属性ref该属性是一个以实例作为参数调用的函数。这也允许您访问不在顶层的对象,例如,如果您正在渲染,<MuiThemeProvider><Hello ref={setHelloRef} /></MuiThemeProvider>您将获得传递给您的setHelloRef函数的正确引用,而不是一个 to MuiThemeProvider
2021-06-11 02:08:28
未捕获的类型错误:_react2.default.render 不是函数
2021-06-17 02:08:28

你可以像

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();
添加全局变量并不是一个好的解决方案。更多关于为什么全局变量不好的信息:wiki.c2.com/?GlobalVariablesAreBad
2021-05-27 02:08:28
它有效,但如果您在同一页面上有多个相同的组件,它将无法工作。
2021-06-02 02:08:28
其实简单又实用!就像它应该是。它的简单性给我留下了深刻的印象;真的没想过。如果您应该有越来越多的组件,这种方法可能不会那么好用。谢谢!
2021-06-05 02:08:28
这正是我需要的务实和简单的解决方案,谢谢!
2021-06-09 02:08:28
感谢投反对票!!是的,全局变量不好,但这是解决问题的一种方法。
2021-06-15 02:08:28

我做过这样的事情:

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 调用,我想保留在该组件中。在这种情况下,这是一个很好的解决方案。

我想你的意思是 this.cowCallbacks.say('moo')
2021-06-02 02:08:28
@WebBrother 是的,但那会更加骇人听闻
2021-06-05 02:08:28
顺便说一句,可以传递this给回调(这将是 Cow 的一个实例)而不是callbacks.
2021-06-09 02:08:28

1.与 React hooks - useImperativeHandle + useRef

const MyComponent = ({myRef}) => {
  const handleClick = () => alert('hello world')
  useImperativeHandle(myRef, () => ({
    handleClick
  }), [/* dependencies (if any) */])
  return (<button onClick={handleClick}>Original Button</button>)
}

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

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

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.current.handleClick}>
        Additional Button
      </button>
    </>
  )
}

祝你好运...

由于该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>

当我尝试这个时,我得到了Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?它并没有将组件绑定到窗口
2021-05-22 02:08:28
最好将引用放在本地状态而不是窗口对象上...... ref={component => {this.setState({ helloComponent: component; })}} 然后,在单击处理程序中...... this.state.helloComponent.alertMessage();
2021-05-25 02:08:28
继我之前的评论......或者,更好的是,只需将组件的 alertMessage 方法置于 state 中。
2021-06-06 02:08:28
也许不是很好的形式,但正是我需要的。谢谢
2021-06-13 02:08:28