In reactjs modal close button is not working - reactjs

I am use bootstrap modal in reactjs project. Here is the link of package which i have installed in my project: https://www.npmjs.com/package/react-responsive-modal
When, I click on open the modal button then it is working, but when i click on close button then close button is not working. I am using the hooks in my project. Below, I have mentioned my code:
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [open, openModal] = useState(false)
const onOpenModal = () => {
openModal({open: true})
};
const onCloseModal = () => {
openModal({open: false})
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={open} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;

The issue is because, you are setting object in state,
openModal({open: true})
This will store object in state.
setState require's direct value which needs to be change, your setState must be this,
const onOpenModal = () => {
openModal(!open) //This will negate the previous state
};
const onCloseModal = () => {
openModal(!open) //This will negate the previous state
};
Demo
You can simplify your code and just use 1 change handle for your modal,
const Login = () => {
const [open, openModal] = useState(false)
const toggleModal = () => {
openModal(!open)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={toggleModal}>Open modal</button>
<Modal open={open} onClose={toggleModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
Demo

Your naming of the model hook is misleading and you're using the setState part of the Hook wrong, probably mixing it up with the this.setState convention for non-Hook React code.
import React, { useState } from 'react'
import Modal from 'react-responsive-modal'
const Login = () => {
const [modalOpen, setModalOpen] = useState(false)
const onOpenModal = () => {
setModalOpen(true)
};
const onCloseModal = () => {
setModalOpen(false)
};
return(
<div>
<h1>Login Form</h1>
<button onClick={onOpenModal}>Open modal</button>
<Modal open={modalOpen} onClose={onCloseModal} center>
<h2>Simple centered modal</h2>
</Modal>
</div>
)
}
export default Login;

Related

using a Popconfirm from antd to confirm the closing of a modal?

I am trying to use a popconfirm of ant design to confirm the closing of a modal, the following code I get the popconfirm to fire and the modal to close, but the popconfirm stays open.
does anyone have any idea how to make the popconfirm close when it is confirmed by giving it yes ?
import { Modal, Popconfirm } from 'antd';
import { useState } from 'react';
export const Ensayo=()=> {
const [open, setOpen] = useState(false);
const [popupOpen, setPopupOpen] = useState(false);
const showModal = () => {
setOpen(true);
};
const handleCancel = () => {
setPopupOpen(true);
};
const handlePopupConfirm = () => {
setOpen(false);
setPopupOpen(false);
};
const handlePopupCancel = () => {
setPopupOpen(false);
};
return (
<div>
<button type="button" onClick={showModal}>
Open Modal
</button>
<Modal
title="Basic Modal"
open={open}
onCancel={handleCancel}
>
<p>Some contents...</p>
<Popconfirm
title="Are you sure you want to close this modal?"
open={popupOpen}
onConfirm={handlePopupConfirm}
onCancel={handlePopupCancel}
okText="Yes"
cancelText="No"
/>
</Modal>
</div>
);
}
I have tried to add the popupOpen condition as a condition for the popconfirm rendering but it doesn't work with that condition it never triggers the popconfirm.
You can move the <Popconfirm> component outside the <Modal>
check the following example
import { Modal, Popconfirm } from "antd";
import { useState } from "react";
export const Ensayo = () => {
const [open, setOpen] = useState(false);
const [popupOpen, setPopupOpen] = useState(false);
const showModal = () => {
setOpen(true);
};
const handleCancel = () => {
setPopupOpen(true);
};
const handlePopupConfirm = () => {
setOpen(false);
setPopupOpen(false);
};
const handlePopupCancel = () => {
setPopupOpen(false);
};
return (
<div>
/* Popconfirm moved here */
<Popconfirm
title="Are you sure you want to close this modal?"
open={popupOpen}
onConfirm={handlePopupConfirm}
onCancel={handlePopupCancel}
okText="Yes"
cancelText="No"
/>
<button type="button" onClick={showModal}>
Open Modal
</button>
<Modal title="Basic Modal" open={open} onCancel={handleCancel}>
<p>Some contents...</p>
</Modal>
</div>
);
};
export default Ensayo;
Output:

Why the div doesn't close?

I am trying when I click outside the div to close the div. Here is my code :
import { useRef, useState } from "react";
import "./styles.css";
const App = () => {
const [showModal, setShowModal] = useState(false);
const noderef = useRef(null);
const handleClick = () => {
console.log(showModal);
if (!showModal) {
console.log("test1");
document.addEventListener("click", handleOutsideClick, true);
} else {
console.log("test2");
document.removeEventListener("click", handleOutsideClick, true);
}
setShowModal(!showModal);
};
const handleOutsideClick = (e) => {
if (!noderef.current.contains(e.target)) handleClick();
};
return (
<div ref={noderef}>
<button onClick={() => handleClick()}>Open Modal</button>
{showModal ? (
<div className="modal">
I'm a modal!
<button onClick={() => handleClick()}>close modal</button>
</div>
) : null}
</div>
);
};
export default App;
When I click on Open Modal it works also when I click on close modal. But when I click outside the div the div is still opened.
How can I do to fix that, it looks it is like there are two clicks
Here is the full project : My project

React Button Component doesn't render the label inside the button

I'm creating a simple React App and I've stumbled upon something I can't solve.
I've created a button component which I've exported like any other component.
At the moment, I've imported the Button component in my main part because I need two buttons
The problem is that the labels won't render so i have 2 plain buttons..
The label the button should show is Search
Any fixes?
The Button component
import React from 'react';
import './Button.css';
const Button = ({state = "active"}) => {
return (
<button className={`.btn--${state}`}></button>
);
};
export default Button;
My Main component
import React from 'react';
import './Input.css';
import { useState } from 'react';
import Button from '../Button/Button';
const Input = () => {
const [value, setValue] = useState("");
const SearchButton = (e) => {
e.preventDefault();
console.log("click");
};
const ResetButton = (e) => {
e.preventDefault();
setValue("");
};
return (
<main>
<form className='inputfield'>
<h2 className='input-text'>Zoek een Github user</h2>
<div className='input'>
<input className='search' type='text' placeholder='Typ hier een gebruikersnaam...' value={value} onChange={(e) => setValue(e.target.value)}></input>
<div className='button-field'>
<Button state="inactive" className='search-now' onClick={SearchButton}>Search</Button>
<Button className='reset' onClick={ResetButton}></Button>
</div>
</div>
</form>
</main>
);
};
export default Input;
You have two straight forward ways of this doing what you want.
The first solution would be to use children React Docs Here
Your button then would look like:
const Button = ({state = "active"}) => {
const {children} = props
return (
<button className={`.btn--${state}`}>{children}</button>
);
};
A second approach is to pass the Value through props to the component.
<Button
state="inactive"
className='search-now'
onClick={SearchButton}
textValue={"Search"} />
// Button
const Button = ({state = "active"}) => {
const {textValue} = props
return (
<button className={`.btn--${state}`}>{textValue}</button>
);
};

How to render the infoPage.js page in a seperate window when the user click on handleClick function

I would like to render the infoPage.js when the user clicks to handleClick function in react. Help Appreciated?
infoPage.js
import React from 'react'
export default function infoPage() {
return (
<div>
<h1> this is info components</h1>
</div>
)
}
App.js:
<button className="btn btn-primary" onClick={handleClick}>{value.title}</button>
Function:
const handleClick = () => {
const url = infoPage;
window.open(url, '_blank');
}
If you want to the /infoPage in new window, then try this code it's works.!
const handleClick = () => {
window.open('/infoPage', '_blank', 'location=yes,height=570,width=520,scrollbars=yes,status=yes');
}

Add component to useRef object

How would you add a component inside an useRef object (which is refering to a DOM element)?
const Red = () => {
return <div className="color">Red</div>;
};
const Black = () => {
return <div className="color">Black</div>;
};
const Green = () => {
return <div className="color">Green</div>;
};
const Button = (params) => {
const clickHandler = () => {
let boolA = Math.random() > 0.5;
if (boolA) {
params.containerRef.current.appendChild(<Red />);
} else {
let boolB = Math.random() > 0.5;
if (boolB) {
params.containerRef.current.appendChild(<Black />);
} else {
params.containerRef.current.appendChild(<Green />);
}
}
};
return <button onClick={clickHandler}>Click</button>;
};
export default function App() {
const containerRef = useRef(null);
return (
<div className="App">
<Button containerRef={containerRef} />
<div ref={containerRef} className="color-container">
Color components should be placed here !
</div>
</div>
);
}
params.containerRef.current.appendChild(); -> throws an error. I`ve put it to show what I would like to happen.
Also is what I`m doing an anti-pattern/stupid ? Is there another (smarter) way of achieving the above ?
codesandbox link
edit :
I forgot some important information to add.
Only Button knows and can decide what component will be added.
expecting you want to add multiple colors, something like this would work and don't need the ref:
import { useState } from "react";
import "./styles.css";
const Color = () => {
return <div className="color">Color</div>;
};
const Button = (params) => {
return <button onClick={params.onClick}>Click</button>;
};
export default function App() {
const [colors, setColors] = useState([]);
return (
<div className="App">
<Button onClick={() => setColors((c) => [...c, <Color />])} />
<div className="color-container">
{colors}
</div>
</div>
);
}
It's better to have a state that is changed when the button is clicked.
const [child, setChild] = useState(null);
const clickHandler = () => {
setChild(<Color />);
};
const Button = (params) => {
return <button onClick={params.onClick}>Click</button>;
};
<Button onClick={clickHandler} />
<div className="color-container">
Color components should be placed here !
{child}
</div>
Working sandbox
Edit: Refer to #TheWuif answer if you want multiple Colors to be added upon clicking the button repeatedly
There're several things from your code I think are anti-pattern:
Manipulate the real dom directly instead of via React, which is virtual dom
Render the Color component imperatively instead of declaratively
Here's the code that uses useState (state displayColor) to control whether <Color /> should be displayed
import { useState } from "react";
import "./styles.css";
const Color = () => {
return <div className="color">Color</div>;
};
const Button = (props) => {
return <button onClick={props.clickHandler}>Click</button>;
};
export default function App() {
const [displayColor, setDisplayColor] = useState(false);
const clickHandler = () => {
setDisplayColor(true);
};
return (
<div className="App">
<Button clickHandler={clickHandler} />
<div className="color-container">
Color components should be placed here !{displayColor && <Color />}
</div>
</div>
);
}
Codesandbox

Resources