I am in an event function and I would like to create a new alert popup (I am using the react-portal library):
onNewAlert: function(username) {
var divModal = (
<Portal ref={'Portal'+username}>
<div id={'div'+username}>
<br /><br/ >Alert for {username}
</div>
</Portal>);
...
}
But then I would have to call a function that is inside a Portal. I could normally do this with references if I was in the render() function, but I am in an event.
this.refs['Portal'+username].openPortal(); // openPortal is a function of the Portal component
Is there a way to call a component function for a component created on the fly in a javascript function?
Even if you could call portal.openPortal() it wouldn't do anything since the component created in the event handler wouldn't be attached to the DOM.
Instead of trying to render the Portal in the event handler function, the event handler should change the component state which will trigger render().
onNewAlert: function(username) {
this.setState({ showAlert: true });
}
The render() function would then use the state variable for the Portal component's isOpened property:
render: function () {
return (
<div>
...
<Portal isOpened={this.state.showAlert}>
...
</Portal>
</div>
);
}
Related
I have an svg button that contains children elements(polygons). The handleMouseLeave function is used to set the state and then utilize its callback to update the children immediatley after. Even though the 'mouseleave' and 'callback' logs both fire in order, the rest of the code inside the callback area does not always fire.
Is there a better or correct way to handle the callback?
handleMouseLeave = (e) => {
console.log('mouseleave')
const polygons = [...e.target.children];
this.setState({
translate: "translateX(-100%)",
opacity: 0
}, () => {
console.log('callback')
polygons.forEach(child => {
child.style.transform = this.state.translate;
child.style.opacity = this.state.opacity;
});
});
};
--
render() {
return(
<button>
<HeroButtonSVG
id="HeroButton"
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
/>
<span>Check out my work<i className="fas fa-chevron-right"></i></span>
</button>
);
};
This seems to be an event binding issue, as class methods are not bound by default.
To solve this, you can add the following to the render function, which will bind the event, through using arrow functions to automatically bind:
<HeroButtonSVG
id="HeroButton"
onMouseEnter={e => this.handleMouseEnter(e)}
onMouseLeave={e => this.handleMouseLeave(e)}
/>
It turns out that the actual issue was derived from the pointer-events on the child SVG's. The issue was not related to React's setState callback function.
I tracked the issue here: https://github.com/facebook/react/issues/4492
I want to call the method inside the same class. For example, when I click a button, it will trigger the method handleLoginBtnClicked(). I expect it will call the method checkInputValidation() in the same class. What is the proper way to do this?
export default class LoginCard extends React.Component {
//If I click a button, this method will be called.
handleLoginBtnClicked() {
this.checkInputValidation();
}
checkInputValidation() {
alert("clicked");
}
...
...
...
render() {
...
<LoginBtn onClick={this.handleLoginBtnClicked}/>
...
}
}
Error Message:
Uncaught TypeError: this.checkInputValidation is not a function
You will need to bind those functions to the context of the component. Inside constructor you will need to do this:
export default class LoginCard extends React.Component {
constructor(props) {
super(props);
this.handleLoginBtnClicked = this.handleLoginBtnClicked.bind(this);
this.checkInputValidation = this.checkInputValidation.bind(this);
}
//This is the method handleLoginBtnClicked
handleLoginBtnClicked() {
...
}
//This is the method checkInputValidation
checkInputValidation() {
...
}
...
..
.
}
Where are you binding the handleLoginBtnClicked? You may be losing the functions context and losing the meaning of the special variable this. React will handle and trigger the onClick event, calling the function from a different context which is why it has been lost.
You should use the following syntax to create a new bound function to add as the event listener for the onClick event. This will ensure that handleLoginBtnClicked's context is not lost.
<element onClick={this.handleLoginBtnClicked.bind(this)}>
crafting basic app in react as following:
parent container receive state by ajax and contains four columns, left column - all messages items, second column message body (should be shown when message element is clicked as well as controls), next - message controls (next, prev) and action type:
how to to properly attach a controls to children elements for instance for onClick to message element? here is the snippet of a parent:
var ModerationContainer = React.createClass({
getInitialState: function () {
return {data: []};
},
componentDidMount: function () {
...
},
LoadMessagesFromApi: function () {
jQuery.ajax({
... // loads messages from json api into state
});
},
testor: function () {
alert();
},
render: function () {
var allMessageItems = this.state.data.map(function (message) {
return (
<MessageItem id={message.id} key={message.id} onClick={this.testor}/>
);
}, this);
return (
<div>
<div className="col-md-2 messageColumn">
{allMessageItems}
</div>
<MessageBodyColumn/>
<ControlsColumn />
<BlockColumn />
</div>
);
}
});
No onclick event is executed after i click message block althrought I attached this to map while rendering messages block, what did i wrong ?
Also, how it is possible to auto select first message item if none of them clicked ?
Any hints or links on tutorials from experienced with react people much appreciated
I would right the MessageItem on the parent like
<MessageItem key={message.id} onClick={this.testor.bind(this, message.id) }/>
Then inside your MessageItem component you can take the onClick handler from the pros, lets say MessageItem is a div your render function could be like
render()
{
const onClick = this.props.onClick;
const label = `Message${this.props.key}`;
return( <div onClick={ onClick }> { label }</div>)
}
and if you write your testor like
testor: function ( id ) {
alert( id );
}
You can see the id of the clicked message.
I'm using React to create a UI and I have a parent component and a child component, something along these lines:
// Child component
var ListItem = React.createClass({
render: function() {
var link_details = (
<div>
Start Date: {this.props.my_data.start_date}<br/>
End Date: {this.props.my_data.end_date}<br/>
</div>
);
return (
<li>
<a onClick={this.props.clickHandler}>
{ this.props.my_data.name }
</a>
{link_details}
</li>
)
}
});
// Parent component
var Sidebar = React.createClass({
getInitialState: function() {
return {
my_data: [],
};
},
handleListItemClick: function(e){
console.log(e.target);
console.log(e.target.props);
},
render: function() {
var myLinks = this.state.my_data.map(function(mylink) {
return (
<ListItem key={mylink.id} my_data={mylink} clickHandler={this.handleListItemClick} />
);
}.bind(this));
return (
<div>
<ul className="nav nav-sidebar">
{ myLinks }
</ul>
</div>)
}
});
I want the click event on the child to trigger the parent's handler so that the parent can update its state based on what was clicked in the child. While the code I have above works, and the parent's handler is called, I am unable to access any of the child component's props. I'm not sure if that's by design and I should pass data from the child to the parent in a different way, or if I'm doing something wrong. I'm still very new to React, so any advice is appreciated. Thanks!
You can not do that but you can pass data from child to parent via callback
<li>
<a onClick={this.props.clickHandler.bind(null,this.props.my_data.name)}>
{ this.props.my_data.name }
</a>
{link_details}
</li>
or using arrow function if you are using es6
<li>
<a onClick={() => this.props.clickHandler(this.props.my_data.name)}>
{ this.props.my_data.name }
</a>
{link_details}
</li>
Edit
Why passing null?
Things to remember:
Automatic binding methods to 'this' happens when your component mounts.
There are two conditions
1.Calling a callback passed from parent component to a child component
When we directly pass functions (e.g. this.clickHandler) to a child component without worrying about the value of 'this' when the function is actually called.
React then the replaces the standard Function.prototype.bind method with its own function to help stop you from doing anything silly (like trying to change the already-bound value of 'this'), so you instead have to pass 'null' to say "I understand this will only alter the arguments".
2.Calling a function defined within same component
React does not do this for function calls within the same component
Rules for binding
If you want to set the first argument by calling .bind on a function...
passed in via props, pass null as the first argument e.g.
this.props.funcName.bind(null, "args")
taken from 'this', pass 'this' as the first argument e.g.
this.funcName.bind(this, "args")
You can do so:
var ListItem = React.createClass({
clickItem: function (e) {
this.props.clickHandler(e, this.props.my_data); // now you can pass any data to parent
},
render: function() {
var link_details = (
<div>
Start Date: {this.props.my_data.start_date}<br/>
End Date: {this.props.my_data.end_date}<br/>
</div>
);
return (
<li>
<a onClick={this.clickItem}>
{ this.props.my_data.name }
</a>
{link_details}
</li>
)
}
});
I took a look at the answer on Pass props to parent component in React.js and came up with the following:
// Parent component
var Sidebar = React.createClass({
getInitialState: function() {
return {
my_data: [],
};
},
handleListItemClick: function(data_passed, e){
console.log(data_passed);
},
render: function() {
var myLinks = this.state.my_data.map(function(mylink) {
return (
<ListItem key={mylink.id} my_data={mylink} clickHandler={this.handleListItemClick.bind(null, mylink.id)} />
);
}.bind(this));
return (
<div>
<ul className="nav nav-sidebar">
{ myLinks }
</ul>
</div>)
}
});
This does seem to work- I'd be interested in seeing other solutions and which one is the "best" and why.
I have a link in a React component:
<a href="#goals-tab" className={ this.setTabStyle()}>Goals</a>
Now, inside setTabStyle method, can I access attributes of the a element, like href without explicitly passing it to the method as a parameter?
If you use a ref, then your component renders DOM without the styles, and then applies the new styles. So the user will notice the change of styles.
I would advise to pass link as a parameter to setTabStyle(link), or make the link another prop of your component:
var Component = React.createClass({
handleClick: function (e) {
console.log(e.currentTarget.getAttribute('href'));
},
setTabStyle: function () {
if (this.props.link == this.props.activelink) {
return myActiveLinkStyle
} else {
return myInactiveLinkStyle
}
},
render: function() {
return <a href={this.props.link} style={this.setTabStyle()} onClick={this.handleClick}>Click</a>;
}
});
That way, you get the right style from the initial load..