My ReactJS Modal Window do not work.
Here is code:
import React from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ handleClose, show, children }) => {
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={handleClose}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And here is code in my component:
function modalState(state) {
return state;
};
<Modal show={modalState(setModal)} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
And if I click Add user button then nothing happens:
<Button variant="primary" size="sm" onClick={() => {
setModal = true;
modalState(setModal);
}}>Add User</Button>{' '}
What should I doing wrong?
Try to use useState hook.
Your Modal component.
import { useState } from 'react';
import './Modal.css';
import Button from 'react-bootstrap/Button';
const Modal = ({ show, children }) => {
const [modalState, setModalState] = useState(show);
const showHideClassName = show ? "modal display-block" : "modal display-none";
return (
<div className={showHideClassName}>
<section className="card modal-main">
{children}
<div className="clear"></div>
<Button onClick={() => setModalState(false)}>
Close
</Button>
</section>
</div>
);
};
export default Modal;
And your component where calls Modal component.
import { useState } from 'react';
import Modal from './path/Modal';
const CustomComponent = () => {
const [modalState, setModalState] = useState(false);
return (
<>
<Modal show={modalState}>
{
<div></div>
}
</Modal>
<Button
variant="primary" size="sm"
onClick={() => setModalState(true)}
>
Add User
</Button>
</>
);
}
export default CustomComponent;
But please note that this would be just a temporary solution based on your current codes. If you want a better and permanent solution, I'd like to recommend to implement the global state management thru your whole codebase using Redux or Recoil.
In the onclick event useState set is not done to set the value of the Modal
setModal({modal:true})
And
<Modal show={modal} handleClose={modalState(false)}>
{
<div></div>
}
</Modal>
I think if you do this it will work.
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
Hope this helps you!
You should use setVisibleModal function same page like this code
import React, { useState } from 'react';
const YourComponent = () => {
const [isVisibleModal, setVisibleModal] = useState(false); // <- add
function closeModal() {
setVisibleModal(!isVisibleModal);
};
return (
<>
<Modal show={isVisibleModal} handleClose={closeModal}>
{
<div></div>
}
</Modal>
<Button
variant="primary"
size="sm"
onClick={() => setVisibleModal(true)}
>
Add User
</Button>
</>
)
}
export default YourComponent;
Related
i want to trigger Modal (containing intro.gif) in Electron React Boiletplate on application start, and the modal should close after "intro.gif" finishes.
below is what I've tried so far.
Home.tsx
import { useState } from 'react';
import { Button, Modal } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import Intro from '../../../assets/intro.gif';
function ModalComp() {
const values = [true, 'sm-down', 'md-down', 'lg-down', 'xl-down', 'xxl-down'];
const [fullscreen, setFullscreen] = useState(true);
const [show, setShow] = useState(false);
function handleShow(breakpoint) {
setFullscreen(breakpoint);
setShow(true);
}
return (
<>
{values.map((v, idx) => (
<Button key={idx} className="me-2 mb-2" onClick={() => handleShow(v)}>
Full screen
{typeof v === 'string' && `below ${v.split('-')[0]}`}
</Button>
))}
<Modal show={show} fullscreen={fullscreen} onHide={() => setShow(false)}>
<img src={Intro} className="img-fluid" alt="" />
</Modal>
</>
);
}
function Home() {
return (
<div>
{/* modal start */}
<ModalComp />
{/* modal end */}
</div>
);
}
export default Home;
I am trying to display a Bootstrap modal which is in a different component than the button which open the modal.
Header.js
import React, { useState } from "react";
import Search from "./Search";
function Header() {
const [showModal, setShowModal] = useState(false);
const handleShowModal = () => setShowModal(true);
return (
<header>
<ul>
<li>
<button className="btn" onClick={handleShowModal}>
Search
</button>
</li>
</ul>
<Search shoWChildModal={handleShowModal} />
</header>
);
}
export default Header;
Search.js
import React, { useState } from "react";
import Modal from 'react-bootstrap/Modal';
function Search(shoWChildModal) {
const [showModal, setShowModal] = useState(false);
const handleCloseModal = () => setShowModal(false);
return (
<Modal show={shoWChildModal} onHide={handleCloseModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<button variant="secondary" onClick={handleCloseModal}>
Close
</button>
<button variant="primary" onClick={handleCloseModal}>
Save Changes
</button>
</Modal.Footer>
</Modal>
);
}
export default Search;
Actually the modal opens on page load. Would it be possible to open the modal with the onclick event of the button?
i have a little question, i having use PrimeReact to develop my stuff but sometimes is quite annoying change from classcomponent to functional component, so i want to change this component to funtional, someone can help me?
import React, { Component, useState } from 'react';
import { OverlayPanel } from 'primereact/overlaypanel';
import { Button } from 'primereact/button';
class Datas extends React.Component {
render() {
return (
<div className='content-section implementation'>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => this.op.toggle(e)}
/>
<OverlayPanel ref={el => (this.op = el)}>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => (e)}
/>
</OverlayPanel>
</div>
);
}
}
export default Datas
For a component like this with only a render method translating to a functional component is simply this.
import React, { Component, useState } from 'react';
import { OverlayPanel } from 'primereact/overlaypanel';
import { Button } from 'primereact/button';
const Datas = () => {
return (
<div className='content-section implementation'>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => op.toggle(e)}
/>
<OverlayPanel ref={el => (op = el)}>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => (e)}
/>
</OverlayPanel>
</div>
);
}
export default Datas
import React, { Component, useState } from 'react';
import { OverlayPanel } from 'primereact/overlaypanel';
import { Button } from 'primereact/button';
const Datas = () => {
return (
<div className='content-section implementation'>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => this.op.toggle(e)}
/>
<OverlayPanel ref={el => (this.op = el)}>
<Button
type='button'
icon='pi pi-search'
// label='Toggle'
onClick={e => (e)}
/>
</OverlayPanel>
</div>
);
}
export default Datas
Try to use this component in VS code
Glean
I'm trying to make a reusable confirmation modal with Material UI but when I press CANCEL or OK the modal does not close.
The code is here:
https://codesandbox.io/s/lucid-hoover-sput6?file=/src/App.js
I can't figure it out why the pop don't dissapear.
LE: added the code here so it remains
ConfirmModal.js
import React from "react";
import { Button } from "#material-ui/core";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
const ConfirmModal = (props) => {
const { content, open, setOpen, onConfirm } = props;
return (
<Dialog
open={open}
onClose={() => setOpen(false)}
aria-labelledby="dialog-title"
>
<DialogContent>
<DialogContentText>{content}</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setOpen(false)} color="primary">
Cancel
</Button>
<Button
onClick={() => {
setOpen(false);
onConfirm();
}}
color="primary"
>
OK
</Button>
</DialogActions>
</Dialog>
// </div>
);
};
export default ConfirmModal;
App.js
import React, { useState } from "react";
import { IconButton } from "#material-ui/core";
import { Input as InputIcon } from "#material-ui/icons";
import ConfirmModal from "./ConfirmModal";
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</IconButton>
</div>
);
}
Move the modal out of the button. The Modal's cancel/confirm/backdrop click events are propagating (bubbling) up to the open button (IconButton) and its onClick handler is just reopening the modal by setting confirmOpen state true.
export default function App() {
const [confirmOpen, setConfirmOpen] = useState(false);
const handleLogout = () => {
console.log("this hould logout the user");
};
return (
<div className="App">
<h2>Press the button below so the confirmation modal appears </h2>
<IconButton color="inherit" onClick={() => setConfirmOpen(true)}>
<InputIcon />
</IconButton>
<ConfirmModal
content="Are you sure you want to leeeave us ?"
open={confirmOpen}
setOpen={setConfirmOpen}
onConfirm={handleLogout}
/>
</div>
);
}
Editing for clarity: I cannot figure out how to dynamically create Boostrap Components using JSX in a react app. End goal is to get the new button in the "newBtnSpace" div when the first button is clicked. I have tried using show.hide methods, but those need to be hard coded. Trying to create buttons based off an array. code:
./components/newBSBtnSpaceFunc.js
import React, { Component } from 'react'
import { Button } from 'reactstrap'
export default function NewBSBtnFunc() {
let BtnArray = ["red", "blue", "green"].map((btn) => {
return React.createElement(
Button,
{variant: 'primary'},
'New Button',
{id: "newBtn"},
btn
)
}
./components/BSBtn.js
import React, { Component } from 'react'
import { Button } from 'reactstrap'
import NewBSBtnFunc from "./NewBSBtnFunc"
export default class BSBtn extends Component {
render() {
return (
<div>
<Button onClick={NewBSBtnFunc}>Click Me</Button>
<div id="newBtnSpace"></div>
</div>
)
}
}
App.js
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import BSBtn from "./components/BSBtn"
function App() {
return (
<div>
<BSBtn></BSBtn>
</div>
);
}
export default App;
github link: https://github.com/mollygilbert389/testingBootstrapBtn
You can conditionally show the new button by setting a state item (in this case showNewButton) to true in the onClick of the original button.
render() {
return (
<div>
<Button onClick={() => this.setState({ showNewButton: true }))}>Click Me</Button>
<div id="newBtnSpace">{ this.state.showNewButton && <Button variant="primary" id="newBtn">New Button</Button> }</div>
</div>
)
}
PS you've already successfully worked out how to create Bootstrap buttons in jsx:
<Button onClick={NewBSBtnFunc}>Click Me</Button>
onClick does not expect a return value so returning the new button won't do anything.
The way you have things organized makes it very difficult since you can't return anything from the function, and you can't modify state from outside the class. I would suggest moving your click handler into the component and using to to modify a state value that will show the second button.
Here is my suggestion:
import React, { Component } from 'react'
import { Button } from 'reactstrap'
export default class BSBtn extends Component {
state = {show: false}
handleClick = () => {
this.setState({ show: !this.state.show })
}
render() {
return (
<div>
<Button onClick={this.handleClick}>Click Me</Button>
<div id="newBtnSpace">
{this.state.show ?
<Button variant="primary" id="newBtn">New Button</Button>
: null}
</div>
</div>
)
}
}
Updated solution to your updated question:
class BSBtn extends React.Component {
state = {
show: false,
buttons: []
}
handleClick = () => {
this.setState({ show: !this.state.show })
}
handleAdd = () => {
this.setState({ buttons: [...this.state.buttons, (this.state.buttons.length + 1)] })
}
render() {
return (
<div>
<h3>Option 1</h3>
<button onClick={this.handleClick}>Click Me</button>
<div id="newBtnSpace">
{this.state.show ? [1,2,3].map((value) => (
<div>
<button>Button {value}</button>
</div>
))
: null}
</div>
<hr/>
<div style={{ marginTop: '30px' }}>
<h3>Option 2</h3>
<button onClick={this.handleAdd}>Click Me</button>
{this.state.buttons.map((value) => (
<div>
<button>Button {value}</button>
</div>
))}
</div>
</div>
)
}
}
ReactDOM.render(<BSBtn />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root' />