我来自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>
© 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)...
答案 0 :(得分:3)
访问另一个组件的方法的最直接方法是传递refs,但是您可能应该以其他方式来解决此问题。一旦将组件与ref绑定在一起,就使它们的可重用性降低,使用起来也更加困难。
如果消息列表存储在较高级别,并作为道具传递到Message
组件中,那么您就不需要引用。
因此,我建议将messages
移至Index
组件的状态(甚至可能移至商店),然后将messages
作为道具传递给<Message messages={this.state.messages} />
。
如果您还想从Message
组件中操作消息,那么还可以传递所需的来自<Index>
的任何回调。
下面是一个玩具示例,展示了将状态存储在父组件中并将messages
和addMessage
作为道具传递给<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