admin管理员组文章数量:1394125
I e from vue.js, so I'm still a bit confused about react.
I have a Message ponent, that shows up flash messages:
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>
)
}
}
I use this ponent in my Index ponent:
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="/" ponent={Wele} />
</div>
<footer>
© 2018 stackoverflow
</footer>
<Message />
</div>
</Router>
);
}
}
if (document.getElementById('root')) {
ReactDOM.render(<Index/>, document.getElementById('root'));
}
Ok, so the Index ponent is the one I start with. I import the Message ponent and render it. That works. In chrome react console, I select the Message tag and can add some messages with
$r.setMessage('success','Greetings my old friend!')
The message appears. So now, how can I use the method setMessage in my Index ponent? In vue.js it's so simple (use $parent or $children)...
I e from vue.js, so I'm still a bit confused about react.
I have a Message ponent, that shows up flash messages:
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>
)
}
}
I use this ponent in my Index ponent:
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="/" ponent={Wele} />
</div>
<footer>
© 2018 stackoverflow.
</footer>
<Message />
</div>
</Router>
);
}
}
if (document.getElementById('root')) {
ReactDOM.render(<Index/>, document.getElementById('root'));
}
Ok, so the Index ponent is the one I start with. I import the Message ponent and render it. That works. In chrome react console, I select the Message tag and can add some messages with
$r.setMessage('success','Greetings my old friend!')
The message appears. So now, how can I use the method setMessage in my Index ponent? In vue.js it's so simple (use $parent or $children)...
Share Improve this question asked Jul 19, 2018 at 9:36 DaFunkyAlexDaFunkyAlex 1,9692 gold badges25 silver badges36 bronze badges 2- 2 I see answers popping up mentioning refs, but before you get excited about them, I remend you read reactjs/docs/refs-and-the-dom.html – Tom Fenech Commented Jul 19, 2018 at 9:42
- Yeah you should avoid this bottom up dataflow in React and inverse it via passing messageArray to Message Component and handle this setMessage stuff in the Index – 42tg Commented Jul 19, 2018 at 9:48
3 Answers
Reset to default 3The most direct way to access the methods of another ponent is to pass refs, but you should probably approach the issue in a different way. Once you start tying your ponents together with refs, you make them less reusable and more difficult to work with.
If the list of messages were stored at a higher level, and passed into your Message
ponent as a prop, then you would have no need for refs.
So I would remend moving messages
into the state of the Index
ponent (or possibly even to a store), then passing messages
as a prop to <Message messages={this.state.messages} />
.
If you also want to manipulate the messages from within the Message
ponent, then also pass whatever callbacks from <Index>
that you need.
Below is a toy example showing the general idea of storing the state in the parent ponent and passing messages
and addMessage
as props to <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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
You can use refs
to get the reference to the element e.g.
<Message refs={(ref) => this.messageElement = ref }/>
With that you can call methods on it from anywhere after it has been assigned
this.messageElement.setMessage();
You can use refs (references) as
<Message ref={(c) => this.messageComponent = c} />
and make functions of Message
ponent with context bound so that it is accessible in other ponents like
Message
Component
constructor(props) {
super(props);
this.state = {messages: []};
this.setMessage = this.setMessage.bind(this);
}
Usage in Index
ponent
this.messageComponent.setMessage('type','body');
Read more of refs here
本文标签: javascriptreactjs call a function from another componentStack Overflow
版权声明:本文标题:javascript - react.js: call a function from another component - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744766751a2624088.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论