react.js:从另一个组件调用一个函数

时间:2018-07-19 09:36:15

标签: javascript reactjs

我来自vue.js,所以我对反应还是有些困惑。

我有一个Message组件,它显示Flash消息:

import React, {Component} from "react";

export default class Message extends Component {

    constructor(props) {
        super(props);
        this.state = {messages: []};
    }

    setMessage(type, body) {
        this.setState({messages: this.state.messages.concat({type: type, body: body})})
        setTimeout(() => {
            this.removeMessage()
        }, 10000);
    }

    removeMessage() {
        let messages = this.state.messages;
        messages.shift();
        this.setState({messages: messages});
    }

    render() {
        return (
            <div className="uk-messages">
                {
                    this.state.messages.map((message, index) => {
                        if (message.type === 'error') {
                            message.type = 'danger';
                        }

                        return (
                            <div className={'uk-alert-' + message.type} data-uk-alert key={index}>
                                <p>{message.body}</p>
                            </div>
                        )
                    })
                }
            </div>
        )    
    }    
}

我在索引组件中使用此组件:

import React, {Component} from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter as Router, Link, Route, Redirect} from 'react-router-dom'
import Auth from './helpers/auth'
import Message from './helpers/message'

class Index extends Component {
    constructor(props) {
        super(props);
        this.state = {
            authState: Auth.state,
        };
        Auth.initialize();    
    }

    render() {
        return (    
            <Router>
                <div className="uk-flex uk-flex-column">
                    <nav className="uk-navbar-container" data-uk-navbar>
                        <div className="uk-navbar-left">
                            <a className="uk-navbar-item uk-logo" href="#"><img src={'images/logo.png'}/></a>

                            <ul className="uk-navbar-nav">
                                <li><Link to="/">Home</Link></li>
                            </ul>
                        </div>
                        <div className="uk-navbar-right">
                            <ul className="uk-navbar-nav">
                                <li>
                                    <a href="#" className="uk-open" aria-expanded="true">
                                        <span data-uk-icon="icon: user" />
                                    </a>

                                </li>

                            </ul>
                        </div>
                    </nav>
                    <div className="uk-flex-grow-1">
                        <Route path="/" component={Welcome} />
                    </div>
                    <footer>
                        &copy; 2018 stackoverflow.com
                    </footer>
                    <Message />
                </div>    
            </Router>
        );
    }

}

if (document.getElementById('root')) {
    ReactDOM.render(<Index/>, document.getElementById('root'));
}

好的,所以索引组件是我开始使用的组件。我导入消息组件并进行渲染。这样可行。在chrome react控制台中,我选择Message标签,并可以添加一些消息,

  

$ r.setMessage('success','问候我的老朋友!')

消息出现。因此,现在如何在索引组件中使用setMessage方法?在vue.js中,它是如此简单(使用$ parent或$ children)...

3 个答案:

答案 0 :(得分:3)

访问另一个组件的方法的最直接方法是传递refs,但是您可能应该以其他方式来解决此问题。一旦将组件与ref绑定在一起,就使它们的可重用性降低,使用起来也更加困难。

如果消息列表存储在较高级别,并作为道具传递到Message组件中,那么您就不需要引用。

因此,我建议将messages移至Index组件的状态(甚至可能移至商店),然后将messages作为道具传递给<Message messages={this.state.messages} />

如果您还想从Message组件中操作消息,那么还可以传递所需的来自<Index>的任何回调。

下面是一个玩具示例,展示了将状态存储在父组件中并将messagesaddMessage作为道具传递给<Message>的一般思想。

const Message = ({ messages, addMessage }) => (
  <div>
    {messages.map(({ text, id }) => <div key={id}>{text}</div>)}
    <button onClick={addMessage}>add</button>
  </div>
);

class Index extends React.Component {
  constructor(props) {
    super(props);
    this.addMessage = this.addMessage.bind(this);
  }

  state = {
    messages: [],
    id: 0
  };
  
  addMessage() {
    this.setState({ 
      messages: [...this.state.messages, { text: "new message", id: this.state.id }],
      id: this.state.id + 1
    });
  }
  
  render() {
    return <Message messages={this.state.messages} addMessage={this.addMessage} />
  }
}

ReactDOM.render(<Index/>, document.getElementById("root"));
<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="root"></div>

答案 1 :(得分:1)

您可以使用refs来获取对元素的引用,例如

<Message refs={(ref) => this.messageElement = ref }/>

有了它,您就可以在分配它之后的任何地方调用方法

this.messageElement.setMessage();

答案 2 :(得分:1)

您可以将refs(引用)用作

 <Message ref={(c) => this.messageComponent = c} />

并使Message组件的功能与上下文绑定,以便可以在其他组件(如

)中访问

Message组件

 constructor(props) {
        super(props);
        this.state = {messages: []};
        this.setMessage = this.setMessage.bind(this);
    }

Index组件中的用法

  this.messageComponent.setMessage('type','body');

阅读更多参考文献here