Reputation:
I'm trying to trap an onclick method on a React component to create a React Modal.
I've added react-overlay
as a dependency and added it to my file.
import Modal from 'react-overlays';
This is the anchor element,
<a href="#" onClick={this.handleClick} data-id={image.id}>
This is the handleclick method,
handleClick(event) {
event.preventDefault();
let mediaId = event.currentTarget.attributes['data-id'].value;
this.setState({ overlay: <Modal show={this.state.showModal} onHide={this.close} mediaId={mediaId}/> });
}
I get the following error,
Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components).
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.(…)
Upvotes: 1
Views: 5231
Reputation: 357
In case anyone still has an issue with this, a modern approach is to build the modal using React hooks. as shown below
import React from 'react';
import './modal.css';
import FontAwesome from 'react-fontawesome';
const Modal = (props) => {
const { closeModal } = props;
const closeicon = () => (
<FontAwesome
name="times"
onClick={closeModal}
style={{
color: '#000000',
padding: '10px',
cursor: 'pointer',
backgroundColor: 'transparent',
border: 0,
position: 'absolute',
top: '0.3rem',
right: '0.5rem',
}}
/>
);
return (
<div className="overlay">
<div className="content">
{ closeicon() }
{props.children}
</div>
</div>
);
};
export default Modal;
The css is as shown below
.overlay {
position: fixed;
display: block;
overflow: auto;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 999;
cursor: pointer;
}
.content {
margin: 15% auto;
background-color: white;
border-radius: 0.25rem;
width: 50vw;
padding: 2rem;
position: relative;
}
So you can use the modal component like this
const [status, setStatus] = useState(false);
//this button will trigger the modal
<button onClick={() => setStatus(true)}>Open Modal</button>
{
status && (
<Modal closeModal={() => setStatus(false)}><p>hello worls</p></Modal>
)
}
No need to worry about responsiveness It's been taken care of in the styling.
For further explanation, you can check this link https://dev.to/adeyemiadekore2/how-to-build-a-reusable-and-responsive-modal-in-react-from-scratch-1o0f
Upvotes: 0
Reputation: 571
Looks like you're importing undefined
..
Also, take a look at https://github.com/fckt/react-layer-stack. This is universal and clean way to solve the "modal problem" in React. Demo - https://fckt.github.io/react-layer-stack/
Upvotes: 0
Reputation: 1757
Your state should contain information that allows you to render the modal, but not the modal itself.
It's highly unusually to store components in state.
Try this:
handleClick()
render()
, render the modal if the flag is set.Let me know if you need an example.
Upvotes: 0
Reputation: 41
I recently had this problem and got around it by creating a Modal-component.
import Modal from 'react-modal'
export default class CustomModal extends React.Component {
constructor () {
super();
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.state = {
open: false
}
}
openModal () { this.setState(
{open: true});
$(function(){
$("#custom-modal").appendTo("body");
});
}
closeModal () {
this.setState({open: false});
}
componentDidMount(){
$(function(){
$("#custom-modal").appendTo("body");
});
}
render () {
return (
<div>
<button onClick={this.openModal}>My modal</button>
<Modal id="custom-modal" isOpen={this.state.open} onRequestClose={this.closeModal}>
// Modal body content here
<button onClick={this.closeModal}>Close</button>
</Modal>
</div>
);
}
}
And then using it like this:
import CustomModal from '../components/CustomModal'
...
<li><CustomModal/></li>
Hope this is of any help.
Upvotes: 1