I have an overlay which is launched from another React component which have a button that also changes itself. The change happens when the user clicks the button, then the button changes it's classname. It also sends a prop value to the children component which is the overlay. The overlay adds a class depending on the property and if it is clicked. Everthing is working pretty nice, but now I have to do another thing. When a user click on the overlay, it have to close up. Before this change, everything was working for the button I mentioned earlier.
Well this is the button component:
export default class StatusBarButton extends React.Component {
constructor(props) {
super(props)
this.state = {active: false}
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ active: !this.state.active });
}
render() {
var cx = require('classnames');
var button = cx ({
'statusbar-button-container' : true,
'active' : this.state.active
});
var animation = cx ({
'statusbar-button-cross-image' : true,
'rotate' : true,
'active' : this.state.active
});
return (
<div className="astatusbar-center-wrapper">
<div className={button} onClick={this.handleClick}>
<img src="images/navbar-element-icon-cross.png" className={animation}/>
</div>
<OverlayView isOpen={this.state.active} />
</div>
);
}
}
And this is the Overlay at the moment:
export default class OverlayView extends React.Component {
constructor (props){
super(props);
this.state = {open: false}
this.setState({ open: this.props.isOpen });
}
render() {
var cx = require('classnames');
var overlay = cx({
'overlay': true,
'overlay-slidedown': true,
'open': this.state.open
});
return (
<div className={overlay} onClick={this._closeOverlay}>
<div className="overlay-menu-wrapper">
<OverlayNewInvoiceButton />
<OverlayNewBudgetButton />
<OverlayNewTicketButton />
</div>
</div>
);
}
}
As you see I'm trying to get the prop value and assign it to the state, but it's not working. How can I assign the prop value to the state and use it?
Regards,
JP
You are missing componentWillReceiveProps(props) method in your OverlayView component.
export default class OverlayView extends React.Component {
constructor (props){
super(props);
this.state = {open: props.isOpen}
}
componentWillReceiveProps(props) {
this.setState({open: props.isOpen});
}
render() {
let open = '';
if (this.state.open === true) {
open = 'open';
}
let overlayClass = `overlay overlay-slidedown ${open}`;
return (
<div className={overlayClass} onClick={this._closeOverlay}>
<div className="overlay-menu-wrapper">
<span>{open}</span>
</div>
</div>
);
}
}
Full working example:
https://codesandbox.io/s/35wLR4nA
constructor(props, context) {
super(props, context);
this.state = {
value: ''
};
}
componentWillReceiveProps(){ //this is called to before render method
this.setState({
value:this.props.data
})
You're problem might be that you are trying to fetch the class props with this
. I think you are supposed to use the props passed into the constructor.
Like this:
constructor (props){
super(props);
this.state = {open: false}
this.setState({ open: props.isOpen });
}
Not sure why you aren't doing it in one line like this though: this.setState = { open: props.isOpen };
Finally i conserved the property which changes the class, is not bad that way. and i fixed with the help of this: Pass props to parent component in React.js and of course the help of a work mate. the end version is this:
This is the parent:
export default class StatusBarButtonView_Profit extends React.Component {
constructor(props) {
super(props)
this.state = {active: false}
this._openOverlay = this._openOverlay.bind(this)
this._closeOverlay = this._closeOverlay.bind(this)
}
_openOverlay() {
if (this.state.active == false) {
this.setState({ active: true });
console.log('boton lanza overlay');
} else {
this.setState({ active: false });
console.log('boton cierra overlay');
}
}
_closeOverlay(Overlay) {
if (this.state.active == true) {
this.setState({ active: false });
} else {
this.setState({ active: true });
}
}
render() {
var cx = require('classnames');
var button = cx ({
'aui-profit-statusbar-button-container' : true,
'active' : this.state.active
});
var animation = cx ({
'aui-profit-statusbar-button-cross-image' : true,
'rotate' : true,
'active' : this.state.active
});
return (
<div className="aui-profif-statusbar-center-wrapper">
<div className={button} onClick={this._openOverlay}>
<img src="images/aui-navbar-element-icon-cross.png" className={animation}/>
</div>
<OverlayView_Profit isOpen={this.state.active} onClick={this._closeOverlay}/>
</div>
);
}
}
this is the child:
export default class OverlayView_Profit extends React.Component {
constructor (props){
super(props);
}
_closeOverlay() {
this.props.onClick();
}
render() {
var cx = require('classnames');
var overlay = cx({
'aui-overlay': true,
'aui-overlay-slidedown': true,
'open': this.props.isOpen
});
return (
<div className={overlay} onClick={this._closeOverlay.bind(this)}>
<OverlayNewInvoiceButtonView_Profit />
<OverlayNewBudgetButtonView_Profit />
<OverlayNewTicketButtonView_Profit />
</div>
);
}
}
now everything works fine.