Modal doesn't open in Header Component
See original GitHub issueSummary:
Hi guys, I bump into an issue when I try to connect redux store into my Modal component in my Header Component, when I dispatched the handleOpenModal function, it produced an uncaught error:
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it’s defined in. Check the render method of
Header
. at invariant (invariant.js:45) at instantiateReactComponent (instantiateReactComponent.js:75) at instantiateChild (ReactChildReconciler.js:45) at ReactChildReconciler.js:72 at traverseAllChildrenImpl (traverseAllChildren.js:78) at traverseAllChildrenImpl (traverseAllChildren.js:94) at traverseAllChildren (traverseAllChildren.js:173) at Object.instantiateChildren (ReactChildReconciler.js:71) at ReactDOMComponent._reconcilerInstantiateChildren (ReactMultiChild.js:186) at ReactDOMComponent.mountChildren (ReactMultiChild.js:225)
After that, the showModal state turns out to be true, however, the modal component didn’t render.
Header.jsx
import React from 'react';
import {connect} from 'react-redux'
import { NavDropdown, MenuItem, ListGroup, ListGroupItem, Button } from 'react-bootstrap';
import { Router, Route, Link, History } from 'react-router';
import { Navbar } from '../Navbar/Navbar'
import Modal from 'react-modal';
import autobind from 'react-autobind'
import Login from '../Pages/Login'
import { openModal, closeModal } from './actions'
const data = [
{
navName: 'Social Media',
iconName: 'fa-heartbeat',
route: 'dashboards/social-media',
},
{
navName: 'Movement',
iconName: 'fa-users',
route: 'dashboards/movement',
},
{
navName: 'Computer Vision',
iconName: 'fa-desktop',
route: 'dashboards/cv',
},
{
navName: 'Social Media',
iconName: 'fa-heartbeat',
route: 'dashboards/modal',
},
{
navName: 'Help',
iconName: 'fa-info-circle',
route: 'dashboard5',
},
{
navName: 'Contact',
iconName: 'fa-comments',
route: 'dashboard6',
},
]
// Necessary to create listGroup inside navigation items
class CustomListGroup extends React.Component {
render() {
return (
<ul className="list-group">
{this.props.children}
</ul>
);
}
}
class Header extends React.Component {
constructor(props){
super(props)
this.state = {
showModal: this.props.showModal
}
autobind(this);
}
handleOpenModal (e) {
console.log('call open modal');
e.preventDefault();
this.props.dispatch(openModal())
}
handleCloseModal () {
this.props.dispatch(closeModal())
}
render() {
const ddAlertTitle = (
<span>
<em className="icon-dashboard"></em>
Dashboard
</span>
)
const {showModal} = this.props
return (
<header className="topnavbar-wrapper">
{ /* START Top Navbar */ }
<Modal
isOpen={showModal}
style={{
content: {
width: '50%',
height: '50%',
'min-width': '300px',
'max-width': '800px',
left: '50%',
top: '50%',
'-webkit-transform': 'translateX(-50%) translateY(-50%)',
'transform': 'translateX(-50%) translateY(-50%)'
}
}}
shouldCloseOnOverlayClick={true}
>
<Login/>
<button onClick={this.handleCloseModal} className="closeBtn">X</button>
</Modal>
<nav role="navigation" className="navbar topnavbar align-middle">
{ /* START navbar header */ }
<div className="navbar-header">
<a href="#/" className="navbar-brand">
<div className="brand-logo">
<img src="assets/images/logo-white.png" alt="App Logo" className="img-responsive logo" />
</div>
<div className="brand-logo-collapsed">
<img src="assets/images/logo-single.png" alt="App Logo" className="img-responsive" />
</div>
</a>
</div>
<div className="nav-wrapper">
<ul className="nav navbar-nav navbar-right">
<NavDropdown eventKey={ 3 } title={ ddAlertTitle } className="dropdown-list text-bold" id="basic-nav-dropdown" >
<CustomListGroup>
<ListGroupItem href="javascript:void(0)">
<Link to={data[0].route} title={data[0].route}>
<div className="media-box">
<div className="pull-left">
<em className="fa fa-heartbeat fa-2x text-info"></em>
</div>
<div className="media-box-body clearfix">
<p className="text-bold">Social Media</p>
</div>
</div>
</Link>
</ListGroupItem>
<ListGroupItem href="javascript:void(0)">
<Link to={data[1].route} title={data[1].route}>
<div className="media-box">
<div className="pull-left">
<em className="fa fa-users fa-2x text-warning"></em>
</div>
<div className="media-box-body clearfix">
<p className="m0 text-bold">Movement</p>
</div>
</div>
</Link>
</ListGroupItem>
<ListGroupItem href="javascript:void(0)">
<Link to={data[0].route} title={data[0].route}>
<div className="media-box">
<div className="pull-left">
<em className="fa fa-desktop fa-2x text-success"></em>
</div>
<div className="media-box-body clearfix">
<p className="m0 text-bold">Computer Vision</p>
</div>
</div>
</Link>
</ListGroupItem>
</CustomListGroup>
</NavDropdown>
<li className="active mr-xl" >
<Link title="log in" onClick={this.handleOpenModal}>
<span>Log In</span>
</Link>
</li>
</ul>
</div>
{ /* END Nav wrapper */ }
</nav>
{ /* END Top Navbar */ }
</header>
);
}
}
const mapStateToProps = (state) => {
return { showModal: state.layout.showModal }
}
export default connect(mapStateToProps)(Header)
actions.js:
import React from 'react'
import * as actions from './constants';
export function changeToAdmin(){
return {
type: actions.SWITCH_ADMIN_MODE
}
}
export function openModal(){
return {
type: actions.SHOW_MODAL
}
}
export function closeModal(){
return {
type: actions.HIDE_MODAL
}
}
reducers.js
import {initialState} from '../../reducers/index.js'
const layout = (state = initialState.layout, action) => {
switch (action.type) {
case 'SWITCH_ADMIN_MODE':
return Object.assign({}, state, {
showAdminMode: true,
showModal: false
});
case 'SHOW_MODAL':
return Object.assign({}, state, {
showModal: true
});
case 'HIDE_MODAL':
return Object.assign({}, state, {
showModal: false
});
default:
return state
}
}
export default layout
Issue Analytics
- State:
- Created 6 years ago
- Comments:7
Hi @diasbruno , I think I figured out. It’s been a while, I think it’s fine now.
Thanks,
Han
Yeah I was. It has something to do with TypeScript’s syntax.