I'm trying to create a MessageBox(Modal Box) element which gets inputs to form the Modal Box, The close method in MessageBox somehow doesn't call the parent close and inturn get the Modal disappear, any help please ??
export default class MessageBox extends Component{
constructor(props) {
super(props);
this.close = this.close.bind(this);
}
close(){
this.props.callbackParent;
}
render(){
return (
<div>
<Modal show={this.props.visibility} onHide={this.close}>
<ModalHeader closeButton>
<ModalTitle>{this.props.msgHeader}</ModalTitle>
</ModalHeader>
<ModalBody>{this.props.msgBody}</ModalBody>
</Modal>
</div>
);
}
}
export default class Product extends Component {
constructor(props) {
super(props);
this._initState = {
showModal: false
}
this.state = this._initState;
this.open = this.open.bind(this);
this.close = this.close.bind(this);
}
open(){
this.setState(
{ showModal: true }
);
}
close(){
this.setState(
{ showModal: false }
);
}
render(){
return (
<div>
<Button bsStyle="primary" bsSize="large" onClick={this.open}>
Go!!!
</Button>
<MessageBox visibility={this.state.showModal} msgHeader='Header goes here ...' msgBody='Overlay message body goes here ..' callbackParent={this.close}/>
</div>
);
}
};
It seems you are missing the parenthesis on in the close method of MessageBox.
this.props.callbackParent;
should be
this.props.callbackParent();
(thx to #azium) for the answer.
I got it working by this
export default class MessageBox extends Component{
constructor(props) {
super(props);
}
render(){
return (
<div>
<Modal show={this.props.visibility} onHide={this.props.callbackParent}>
<ModalHeader closeButton>
<ModalTitle>{this.props.msgHeader}</ModalTitle>
</ModalHeader>
<ModalBody>{this.props.msgBody}</ModalBody>
<ModalFooter>
<Button onClick={this.props.callbackParent}>Close</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
Related
function Welcome(props) {
console.log("Welcome Back");
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
<Welcome />
}
render(){
return (
<div>
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
Why function handleClick can't call outer function Welcome? is there any solution to this?
To call that function, you should do as follows:
function welcome(props) {
console.log("Welcome Back");
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
}
render(){
return (
<div>
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
Notice that I've lowercased your Welcome function since Pacalcased function names should be reserved for React Components as a general naming convention.
If your intention is to have Welcome be a React component, then it should return some JSX and then you should render that out inside of the render function of your class component:
function Welcome(props) {
return (<div>Welcome Back!</div>
}
class App extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
welcome()
}
render(){
return (
<div>
<Welcome />
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
If you'd like to hide your welcome message until you click the button, you can use state:
function Welcome(props) {
return (<div>Welcome Back!</div>
}
class App extends React.Component {
constructor(props){
super(props);
this.state = {
showWelcomeMessage: false
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
this.setState({showWelcomeMessage: true})
}
render(){
return (
<div>
{this.state.showWelcomeMessage ? <Welcome /> : null}
<button onClick={this.handleClick}>CLICK HERE </button>
</div>
);
}
}
In your example changing <Welcome /> to Welcome() is enough. But you should use camelCase to define functions. But here is the refactored version.
import React from "react";
const welcome = () => {
console.log("Welcome Back");
};
export default function App() {
const handleClick = () => {
welcome();
};
return (
<div>
<button onClick={handleClick}>CLICK HERE </button>
</div>
);
}
Just change the calling of the outer function "Welcome", because it is not a Component:
handleClick(){
Welcome()
}
Noob question here. How do I fire the toggle component of the Modal from the parent component? I want the modal to open when the button is clicked on the parent component. The button will submit a form and once the form has been submitted I want the modal to fire. I'm trying to get it to fire in function handleSubmit(e)
Child Component: Modal.jsx
class ModalExample extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}
render() {
return (
<div>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
</Modal>
</div>
);
}
}
Path: Parent.jsx
export default function ForgotPassword() {
function handleSubmit(e) {
e.preventDefault();
}
return (
<div className="container h-100">
<ModalExample toggle />
<button onClick={this.handleSubmit}>Open modal</button>
</div>
);
}
You can use refs as follows
export default function ForgotPassword() {
function handleSubmit(e) {
e.preventDefault();
}
return (
<div className="container h-100">
<ModalExample ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.toggle(); }}>Open modal</button>
</div>
);
}
There might be better ways, but the way I've done it is by pulling the toggle function to the parent class and passing both the function and the state value to the modal in props.
You can then call that props function in your modal to toggle its display, although this will turn your pure component into a stateful component.
Child Component: Modal.jsx
class ModalExample extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Modal isOpen={this.props.modal} toggle={this.props.toggle} className={this.props.className}>
<ModalHeader toggle={this.props.toggle}>Modal title</ModalHeader>
</Modal>
</div>
);
}
}
Parent: Parent.jsx
class ForgotPassword() extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}
return (
<div className="container h-100">
<ModalExample toggle={this.toggle} modal={this.state.modal} />
<button onClick={this.handleSubmit}>Open modal</button>
</div>
);
}
I have a Modal component in the Main.js app and I want to trigger it from a different component (in this case Homepage, but I have one component for each page).
I don´t know how to pass a component to be rendered inside the modal.
If it helps I´m using Context API.
App.js
const App = () => {
return (
<div>this is the main app</div>
<Modal />
)
}
ReactDOM.render(<App />, document.getElementById('root'))
Modal.js
class Modal extends Component {
constructor(props) {
super(props)
this.state = {
'open': false
}
}
componentWillReceiveProps(nextProps) {
this.setState({open: nextProps.open})
}
render() {
if (!this.state.open) {
return false
}
return(
<div className="modal">
{this.props.children}
</div>
)
}
}
export default Modal
Homepage.js
class Homepage extends Component {
constructor(props) {
super(props)
this.handleOpenModal = this.handleOpenModal.bind(this)
}
handleOpenModal() {
// here I want to open the modal and pass the <ModalContent /> component
// basically call the <Modal open="true"> from the Main component
}
render() {
return(
<div className="homepage">
<button onClick={this.handleOpenModal}>open the modal</button>
</div>
)
}
}
const ModalContent = () => {
return(
<div>this is the content I want to render inside the modal</div>
)
}
thank you.
I strongly recommend using something like react-modal (npm). It allows you to keep modal content right next to the trigger. It does this by appending a "portal" high up in the DOM and handles appending the content to is.
Your example may look like the following:
import Modal from 'react-modal';
class Homepage extends Component {
constructor(props) {
super(props)
this.state = { modalOpen: false };
this.handleOpenModal = this.handleOpenModal.bind(this)
}
handleOpenModal() {
this.setState({ modalOpen: true });
}
render() {
return(
<div className="homepage">
<button onClick={this.handleOpenModal}>open the modal</button>
<Modal open={this.state.modalOpen}>
<ModalContent />
</Modal>
</div>
)
}
}
const ModalContent = () => {
return(
<div>this is the content I want to render inside the modal</div>
)
}
I am trying React.js for the first time in trying to build this web app. I am getting Cannot read property 'setState' of null on the specified line below. I've been trying to figure out why for the past few hours and cannot seem to figure it out. Any help would be greatly appreciated.
MyModal.jsx
import React from 'react';
import { Modal, Button, ButtonToolbar } from 'react-bootstrap';
export default class MyModal extends React.Component {
constructor(props) {
super(props);
this.state = {show: false};
}
showModal() {
this.setState({show: true});
}
hideModal() {
this.setState({show: false});
}
render() {
return (
<ButtonToolbar>
<Button bsStyle="primary" onClick={this.showModal}>
Launch demo modal
</Button>
<Modal
{...this.props}
show={this.state.show}
onHide={this.hideModal}
dialogClassName="custom-modal"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-lg">Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>
<h4>Wrapped Text</h4>
<p>Blah</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.hideModal}>Close</Button>
</Modal.Footer> // Chrome inspector says it errors on this line
</Modal>
</ButtonToolbar>
);
} // end render function
} // end export default
bind your component class methods inside the constructor() (binding inside constructor is better than binding inside render() for performance sake):
constructor(props) {
super(props);
this.state = {show: false};
this.showModal = this.showModal.bind(this);
this.hideModal = this.hideModal.bind(this);
}
I'm trying to append a Modal component to the doc body on click of a trigger, but I think my syntax is wrong...
openModal() {
console.log(this.state.isModalOpen);
this.setState({ isModalOpen: true });
$('body').append(
<Modal isOpen={this.state.isModalOpen} transitionName="modal-anim">
<NewAlbum onClick={this.closeModal}/>
</Modal>
)
}
<button onClick={this.openModal}>Trigger</button>
Yeah you have missed a few of the React fundamentals. You need to let React take care of your rendering for you. This is the typical usage for what you are after:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { isModalOpen: false };
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal() {
this.setState({ isModalOpen: !this.state.isModalOpen });
}
render() {
return (
<div>
<button onClick={this.toggleModal}>Trigger</button>
<Modal isOpen={this.state.isModalOpen} transitionName="modal-anim">
<NewAlbum onClick={this.toggleModal}/>
</Modal>
</div>
)
}
}
I would highly recommend you go through the react documentation and get some of the foundations cemented: https://facebook.github.io/react/docs/tutorial.html