从外部调用React组件方法

时间:2015-07-24 14:04:21

标签: reactjs

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

例如,在此jsfiddle https://jsfiddle.net/r6r8cp3z/中,我想从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')
);

14 个答案:

答案 0 :(得分:46)

有两种方法可以访问内部函数。一个是实例级,就像你想要的那样,是另一个静态级别。

实例

您需要在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()

答案 1 :(得分:16)

我做过这样的事情:

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

}

我没有测试过这个确切的代码,但这与我在我的项目中所做的一致,并且它运行良好:)。当然这是一个不好的例子,你应该只使用道具,但在我的情况下,子组件做了一个API调用,我想保留在该组件内。在这种情况下,这是一个很好的解决方案。

答案 2 :(得分:15)

你可以这样做

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

答案 3 :(得分:5)

使用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>
    </>
  )
}

祝你好运...

答案 4 :(得分:3)

使用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>

答案 5 :(得分:2)

您可以使用函数(onClick是React自己的onClick实现)向div添加onClick处理程序,然后您可以在{ }卷内访问该属性大括号和警报信息将会出现。

如果您希望定义可在组件类上调用的静态方法,则应使用静态。虽然:

“此块中定义的方法是静态的,这意味着您可以在创建任何组件实例之前运行它们,并且这些方法无法访问组件的道具或状态。如果要检查道具的值在静态方法中,让调用者将props作为静态方法的参数传递。“ (source

一些示例代码:

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

希望这会对你有所帮助,因为我不知道我是否理解你的问题,所以如果我解释错了,请纠正我:)

答案 6 :(得分:2)

似乎不推荐使用静态,而使用render公开某些函数的其他方法似乎很复杂。与此同时,this Stack Overflow answer about debugging React虽然看似黑客,却为我做了这份工作。

答案 7 :(得分:2)

如果您在ES6中,只需使用&#34;静态&#34;您示例中的方法关键字如下:static alertMessage: function() { ...
},

希望可以帮助那里的任何人:)

答案 8 :(得分:1)

我使用此辅助方法来渲染组件并返回组件实例。 可以在该实例上调用方法。

/**
 * Send netlink message and check & extend header values as needed.
 * @arg sk      Netlink socket.
 * @arg msg     Netlink message to be sent.
 *
 * Checks the netlink message \c nlh for completness and extends it
 * as required before sending it out. Checked fields include pid,
 * sequence nr, and flags.
 *
 * @see nl_send()
 * @return Number of characters sent or a negative error code.
 */
 int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
 {
   struct nlmsghdr *nlh;
   struct nl_cb *cb = sk->s_cb;

nlh = nlmsg_hdr(msg);
if (nlh->nlmsg_pid == 0)
    nlh->nlmsg_pid = sk->s_local.nl_pid;

if (nlh->nlmsg_seq == 0)
    nlh->nlmsg_seq = sk->s_seq_next++;

if (msg->nm_protocol == -1)
    msg->nm_protocol = sk->s_proto;

nlh->nlmsg_flags |= NLM_F_REQUEST;

if (!(sk->s_flags & NL_NO_AUTO_ACK))
    nlh->nlmsg_flags |= NLM_F_ACK;

if (cb->cb_send_ow)
    return cb->cb_send_ow(sk, msg);
 else
 return nl_send(sk, msg);
 }

答案 9 :(得分:1)

在 React17 中你可以使用 useImperativeHandle 钩子。

useImperativeHandle 自定义使用 ref 时暴露给父组件的实例值。与往常一样,在大多数情况下应该避免使用 refs 的命令式代码。 useImperativeHandle 应该与 forwardRef 一起使用:

function FancyInput(props, ref) {
    const inputRef = useRef();
    useImperativeHandle(ref, () => ({
        focus: () => {
            inputRef.current.focus();
        }
    }));

    return <input ref={inputRef} ... />;
}

FancyInput = forwardRef(FancyInput);

在这个例子中,渲染的父组件将能够调用 inputRef.current.focus()。

答案 10 :(得分:0)

docker import myapp.tar.gz myapp:latest

您可以使用class AppProvider extends Component { constructor() { super(); window.alertMessage = this.alertMessage.bind(this); } alertMessage() { console.log('Hello World'); } } 从窗口调用此方法。

答案 11 :(得分:0)

方法1 col_metaData[col_metaData$b %in% inputList,]$sample

using ChildRef

方法2: 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>

using window register

答案 12 :(得分:0)

对于这个问题,我有两个答案:

1-将您的函数用作静态方法:

    statics: {
    alertMessage: function () {
        console.log('Method One');
    }
},

但是此方法有一个大问题,因为在静态方法中您无权访问this,并且在您要使用this的情况下此方法不起作用,因此在这种情况下,请使用方法2。

2-首先进入您的class

constructor(props){
    super(props);
    window.alertMessage = this.alertMessage.bind(this);
}

alertMessage () {
    console.log('Method Two');
}

然后在每个组件中都可以使用以下命令:

答案 13 :(得分:0)

对于动态组件,我使用了带有 props 的 getDerivedStateFromProps 方法。

您可以创建更新子组件 props 的函数,子组件中的 getDerivedStateFromProps 将为您处理 props 的更新。 例如:

class Parent extends React.Component
{
    constructor(props)
    {
        super(props);

        this.state = {  selectMachine: '1' };

        this.setComponent = null;
       
    }

     handleMachineChange = (e) =>{
        this.setState({selectMachine: e.target.value})
    }

}

class Child extends React.Component
{
    state = {
        programForm: {
            machine_id: '1',
           }
    }

    constructor(props)
    {
        super(props);
    }


    static getDerivedStateFromProps(props, state) {
        if(props.selectMachine !== state.programForm.machine_id){
            //Change in props
            return{
                programForm:  { ...state.programForm, machine_id: props.selectMachine }
            };
        }
        return null; // No change to state
    }
}
相关问题