The following React component handles the enter and exit animations of my site's notifications, which it receives through this.props.children
:
class NotificationWrapper extends React.Component {
constructor( props ) {
super( props );
this.state = { timer: setTimeout( this.props.hideNotification, 3000 ) }
}
static getDerivedStateFromProps( props, state ) {
if( props.notification.override ) {
clearTimeout( state.timer );
return {
timer: setTimeout( props.hideNotification, 3000 )
}
}
return null;
}
handleCloseNotification() {
this.props.hideNotification();
}
render() {
return(
<CSSTransition
appear
classNames="v-slide"
in={ this.props.in }
mountOnEnter
timeout={ 200 }
unmountOnExit
onEntered={ () => { this.state.timer } }
>
{ this.props.children }
</CSSTransition>
);
}
}
function mapStateToProps( { notification } ) { return { notification } }
export default connect( mapStateToProps, { hideNotification } )( NotificationWrapper );
It generally works fine, but I would like to pass the hideNotification
prop to this.props.children
so that, besides being hidden automatically after three seconds, the notification can also be hidden at the click of a 'close' button which is included in the children components.
I've read about React.cloneElement()
and tried replacing my this.props.children
with the following:
{
React.cloneElement( this.props.children, {
handleHideNotification: this.props.hideNotification
})
}
but when I test it, as soon as the notification is mounted to the DOM React throws this error:
Invalid value for prop
handlehidenotification
on tag. Either remove it from the element, or pass a string or number value to keep it in the DOM
I can't understand what the problem is...
As props.chidren
is like a list of components, you must iterate over it:
{React.Children.map(this.props.children, child => {
return React.cloneElement(child, { handleHideNotification: 'your prop here' });
})}
I think the best way to solve your problem is to include a close button with a onClick
event which fires a method which will call props.hideNotification
. You will have to add the button just before you inject props.children
.
import React, { Fragment } from 'React'; class NotificationWrapper extends React.Component { constructor( props ) { super( props ); this.state = { timer: setTimeout( this.props.hideNotification, 3000 ) } } static getDerivedStateFromProps( props, state ) { if( props.notification.override ) { clearTimeout( state.timer ); return { timer: setTimeout( props.hideNotification, 3000 ) } } return null; } handleCloseNotification() { this.props.hideNotification(); } render() { return( <CSSTransition appear classNames="v-slide" in={ this.props.in } mountOnEnter timeout={ 200 } unmountOnExit onEntered={ () => { this.state.timer } } > <Fragment> <button onClick="handleCloseNotification">Close</button> { this.props.children } </Fragment> </CSSTransition> ); } }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.