I decided to use the react-draggable npm package for my modal window using ant-design, (for those who don't know react-draggable, this is a simple component for making elements draggable). But I am having difficulty, I tried to wrap my modal window inside but I got an error.
Cannot read property 'className' of undefined
import React, { useState } from "react";
import "antd/dist/antd.css";
import Modal from "antd/es/modal/Modal";
import Draggable from "react-draggable";
import Button from "antd/es/button";
const App = (props) => {
const [visible, setVisible] = useState(false);
return (
<Draggable>
<Button onClick={() => setVisible(true)} type="primary">
Themes
</Button>
<Modal
title="Customize the theme to your liking"
centered
visible={visible}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
width={700}
>
<div className={"SideBarModal_Wrapper"}>
<div className={"SideBarModal_Appearance"}>
<div className={"SideBarModal_Child_Appearance"}>
<p>Appearance</p>
</div>
<div>{props.SideBarWallpaperList}</div>
</div>
<div className={"SideBarModal_Accept_Color"}>
<div className={"SideBarModal_Child_Color"}>
<p>Colors</p>
</div>
<div>{props.list}</div>
</div>
</div>
</Modal>
</Draggable>
);
};
export default App;
You can see my code in codesandbox there I have already installed all the required packages, but I could not apply react-draggable. Here is the link https://codesandbox.io/s/xenodochial-mendel-4bdun
I believe you need to have a single child element in Draggable.
So either put only the Button in the Draggable or wrap your Button and Modal in a div.
updated: https://codesandbox.io/s/currying-river-olme0?file=/src/App.js
The documentation says it loud and clear, Only a single child is allowed or an Error will be thrown. :)
Bind the child components as one single child. (e.g, using a div as I've done below)
import React, { useState } from "react";
import "antd/dist/antd.css";
import Modal from "antd/es/modal/Modal";
import Draggable from "react-draggable";
import Button from "antd/es/button";
const App = (props) => {
const [visible, setVisible] = useState(false);
return (
<Draggable>
<div>
<Button onClick={() => setVisible(true)} type="primary">
Themes
</Button>
<Modal
title="Customize the theme to your liking"
centered
visible={visible}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
width={700}
>
<div className={"SideBarModal_Wrapper"}>
<div className={"SideBarModal_Appearance"}>
<div className={"SideBarModal_Child_Appearance"}>
<p>Appearance</p>
</div>
<div>{props.SideBarWallpaperList}</div>
</div>
<div className={"SideBarModal_Accept_Color"}>
<div className={"SideBarModal_Child_Color"}>
<p>Colors</p>
</div>
<div>{props.list}</div>
</div>
</div>
</Modal>
</div>
</Draggable>
);
};
export default App;
The basic concept is actually like this :
import Draggable from 'react-draggable';
<div className="modal fade show d-block" id="myModal">
<div className="modal-dialog">
<Draggable>
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">Modal Heading</h4>
<button type="button" className="close" data-dismiss="modal">×</button>
</div>
<div className="modal-body">
<h4>This is body</h4>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</Draggable>
</div>
</div>
Try to figure out how to change it if you use react-bootstrap
Related
I'm trying to create a Job platform, Where we can Sign up/login as either "Recruiter" or as a "Candidate". The complication I'm facing is I've created a form for both recruiter and candidate. Now I'm trying to switch between those componets. I've come this far
import useToggle from "#rooks/use-toggle"
export default function SignUp() {
const [recruitForm, setRecruitForm] = useToggle(true);
const [candidateForm, setCandidateForm] = useToggle(false);
}
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<div>
<button
onClick={setRecruitForm}>
Recruiter
</button>
<>
{recruitForm && <RecruiterForm /> }
</>
</div>
<div>
<button
onClick={setCandidateForm}
type="button">
Candidate
</button>
<>
{candidateForm && <CandidateForm /> }
</>
</div>
</div>
</form>
</div>
</div>
)
}
Components are within their own context. But I have trouble even coming up with an idea how to handle or switch components without messing up the styling, the way it needs to be is when one instance opens, close the other conundrum / Form.
I'm sharing the output I've got using the useToggle react rooks
Any ideas on how to achieve it with any other hook or with useToggle hook itself or please let me know what I'm doing wrong.
https://www.loom.com/share/d2251bc3b9594782aa0a17aae92c997e {This is the result I've got}
Since thay are two Items you can make use of a boolean and just one state
const [active, setActive] = useState(false)
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<div>
<button
onClick={()=>setActive(true)}>
Recruiter
</button>
<>
{active && <RecruiterForm /> }
</>
</div>
<div>
<button
onClick={()=>setActive(false)}
type="button">
Candidate
</button>
<>
{!active && <CandidateForm /> }
</>
</div>
</div>
</form>
</div>
</div>
)
}
as far as I can understand from your question, that you have created 2 from components for recruiter and candidate and want to show either on of em at a time. If not please do comment, I'll rectify the answer.
instead of checking your toggles when you will be rendering components, do before that, also you only need one toggle for this, better use a use state.
The initial false state for recruiter and true candidate
import React, {useState} from 'react';
export default function SignUp() {
const [switchForm, setSwitchForm] = useState(false);
return (
<div>
<form>
<div className="text-md tracking-wide p-0">
SignUp Form
</div>
<div className="flex flex-row gap-8">
<button
onClick={setSwitchForm(false)}>
Recruiter
</button>
<button
onClick={setSwitchForm(true)}
type="button">
Candidate
</button>
</div>
<div className="flex flex-row gap-8">
<>
{switchForm ? <CandidateForm /> : <RecruiterForm />}
</>
</div>
</form>
</div>
</div>
)};
This is not the actual/accurate code but just to give you the logical idea.
Also just a suggestion, use a custom hook for your parent component (signup.jsx) and put hooks there and import it from their to parent component and may come in use when you are going to submit the forms so that the states
and handler functions can have a common place to share.
I want to do getElementById to give css effect and click to slide function.
how do I use DOM in react? Thank you in advance.
function Auth() {
//this part needs to be fixed
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('body');
signUpButton.addEventListener('click', () =>
container.classList.add('right-panel-active'));
signInButton.addEventListener('click', () =>
container.classList.remove('right-panel-active'));
Here are the classnames that might help you understand my code better.
return (
<div className ="auth">
<div className="body" id="body">
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button className="slide__btn" id='signUp' > Sign In </button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button className="slide__btn" id='signIn' > Sign Up </button>
</div>
</div>
</div>
</div>
</div>
)
}
I guess the propose to use React is that fact you should interact in the component state.
I suggest you use State in your component and add some according to some interaction
function App() {
const [mode, setMode] = React.useState();
const handleMode = (mode) => {
setMode(mode);
};
const containerClasses =
mode === "signUp" ? "body right-panel-active" : "body";
return (
<div className="auth">
<div className={containerClasses} id="body">
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button
className="slide__btn"
id="signUp"
onClick={() => handleMode("signIn")}
>
{" "}
Sign In{" "}
</button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button
className="slide__btn"
id="signIn"
onClick={() => handleMode("signUp")}
>
{" "}
Sign Up{" "}
</button>
</div>
</div>
</div>
</div>
</div>
);
}
You should avoid direct modification of the dom in React. React assumes that it is the only piece of code modifying the dom, and so it won't know about any changes you make. This opens up the possibility of bugs where react changes something on the dom that you don't expect, or doesn't change something you do expect. A simple piece of code like yours won't have these bugs, but best to learn the react way now so you don't run into these issues with more complicated code.
The react way to do this is to pass onClick props to the elements that need it, and to have a state variable which controls the class names. For example:
import React, { useState } from 'react';
function Auth() {
const [showPanel, setShowPanel] = useState(false);
return (
<div className="auth">
<div className={showPanel ? "body right-panel-active" : "body"}>
<SignUp className="test" />
<SignIn className="test" />
<div className="slide__body">
<div className="slides">
<div className="slide SignUp__left">
<p>Already have an account?</p>
<button
className="slide__btn"
onClick={() => setShowPanel(false)}
>
Sign In
</button>
</div>
<div className="slide SignIn__right">
<p>Not a Member?</p>
<button
className="slide__btn"
onClick={() => setShowPanel(true)}
>
Sign Up
</button>
</div>
</div>
</div>
</div>
</div>
);
}
Hi there,
The issue that I faced recently is the next:
I have a parent component MainPage, that has child components ModalJoin (is not shown by default) and ExploreProjects in it. This ExploreProjects component has its own child component ProjectCard which has a button that is supposed to change a state so ModalJoin is shown.
Does anyone have a solution of how do I bind all these, so when the button is clicked ->useState changes to true and ModalJoin pops up? Been trying to link them properly the whole day but still didn't find a solution.
Would appreciate any help!
Have the following files:
Main page
import React, {useState} from 'react'
import ExploreProjects from './ExploreProjects'
import ModalJoin from './ModalJoin'
export default function MainPage() {
const [isOpened, setIsOpened] = useState(false)
return (
<div>
<div className='app'>
<div className="app__body">
<ExploreProjects/>
</div>
</div>
<ModalJoin openModal={isOpened} onClose={() => setIsOpened(false)}/>
</div>
)
}
ExploreProjects
import React from 'react'
import './ExploreProjects.css'
import ProjectCard from './ProjectCard'
function ExploreProjects() {
return (
<div className='explore__projects'>
<div className="filters__section">
<div className='filter__item'>
<h3>Location</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Industry</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Company</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Complexity</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
<div className='filter__item'>
<h3>Duration</h3>
<img src="/images/chevronDown.svg" alt=""/>
</div>
</div>
<div className="projects__section">
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
<ProjectCard />
</div>
</div>
)
}
export default ExploreProjects
ProjectCard
import React, {useState} from 'react'
import './ProjectCard.scss'
export default function ProjectCard({ src, logo, headline, companyName,
complexity, description, projectType, tag }) {
const [setIsOpened] = useState(false)
return (
<div className='project__card'>
<div className="project__card__header">
<img src="/images/rehauIcon.png" alt="" className='company__logo' />
<h3>Logistics Project</h3>
<div className="project__card__company">
<img src="/images/buildingIcon.svg" alt="" />
<p>Rehau</p>
<p>/</p>
<img src="/images/locationIcon.svg" alt="" />
<p>Berlin</p>
</div>
<div className="project__card__complexity">
<div className="basic__complexity"></div>
<p>Basic</p>
</div>
</div>
<div className="project__card__body">
<div>
<h3>Task:</h3>
</div>
<span>Text
<button>More</button>
</span>
</div>
<div className="project__card__bottom">
<div className="project__card__time">
<p>15m ago</p>
</div>
<div className="project__card__recruitment">
<p>Job opportunity</p>
</div>
<div className="project__card__teams">
<p>1/2 teams joined</p>
</div>
<div className="project__card__tag">
<p>#supplychain</p>
</div>
</div>
<div className="project__card__right">
<img src="images/imgHero.png" alt="" className='project__video__info' />
<div onClick={ () => this.setIsOpened(true)} className="join__project__button">
<p>Join</p>
</div>
</div>
</div>
)
}
ModalJoin
import React from 'react'
export default function ModalJoin({openModal, onClose}) {
if (!openModal) return null
return (
<div>
<button onClick={onClose}>Close</button>
HEEEYYYYYY
</div>
)
}
I commented:
You'll need to pass a callback prop down <ExploreProjects onOpenModalJoin={callback} />, and then pass the same callback down from ExploreProjects down to ProjectCard. Then in project card on the button click, you would call that callback.
This is a more full explanation:
export default function MainPage() {
const [isOpened, setIsOpened] = useState(false);
const callback = () => setIsOpened(true);
...
<ExploreProjects onOpenModalJoin={callback} />
function ExploreProjects(props) {
...
<ProjectCard onOpenModalJoin={props.onOpenModalJoin} />
...
And then inside ProjectCard, you would have
onClick={props.onOpenModalJoin}
Lets go with a simple example on how to change state of a parent from a child and manipulate conditional rendering. you have to pass setState to the child and subChild as well and call it from there. That changes parent state and reflects on modal.
Code Sandbox => https://codesandbox.io/s/silent-bush-c6v4d?file=/src/App.js:0-992
Here you go, this should fix your issue.
import React, { useState } from "react";
import "./styles.css";
const ModalJoin = ({ open, close }) => {
const modal = open ? (
<div style={{ background: "pink" }}>
I am ModalJoin
<button onClick = {close}> Close Me</button>
</div>
) : null;
return modal;
};
const ExploreProjects = ({ click }) => {
return (
<div style={{ background: "orange" }}>
I am ExploreProjects
<ProjectCard click={click} />
</div>
);
};
const ProjectCard = ({ click }) => {
return (
<div style={{ background: "grey" }}>
I am ProjectCard
<button onClick={click}>click me to open modal </button>
</div>
);
};
const App = () =>
{
const [modal, setModal] = useState(false)
return (
<div className="App" style={{ background: "lightBlue" }}>
<h1>I am Parent</h1>
<ExploreProjects click = {() => setModal(true)}/>
<ModalJoin open={modal} close={() => setModal(false)} />
</div>
);
};
export default App;
Parent Component Assessment.js
import Header from './Header'
import { Button, Dialog } from '#material-ui/core';
import Dialog1 from './Dialog1'
import {Modal, Button as ButtonBootstrap} from 'react-bootstrap';
const Assessment = () => {
const [show1, setShow1] = useState(false);
const handleClose1 = () => setShow1(false);
const handleShow1 = () => setShow1(true);
return (
<div>
<Dialog1 show1={show1} handleClose1={handleClose1} setShow1={setShow1}/>
<Header/>
<div className="d-flex flex-row">
<div className="d-flex flex-column align-items-start m-3 mx-5">
<div className='m-2 mx-5 visible' style={{borderRadius: "15px", padding: "10px",
paddingRight:"25px", backgroundColor:"#00CCFF"}}>
<h5 className='font-weight-bold'>Are you having any of these following:-</h5>
<div className='d-flex flex-row'>
<ul>
<li>Extremely difficult to breath</li>
<li>Severe Chest pain.</li>
<li>Having a tough time awakening</li>
<li>Losing consciousness</li>
</ul>
<Button onClick={handleShow1}
className="mx-5 my-4 align-content-around"
variant="contained"
style={{maxWidth: "30px", maxHeight: "30px"}}>
Yes
</Button>
</div>
</div>
</div>
</div>
</div>
)
}
export default Assessment
Child Component Dialog1.js
import React from 'react'
import {Modal, Button as ButtonBootstrap} from 'react-bootstrap';
import Stage1 from '../images/nurse level 0.png';
import Assessment from './Assessment';
const Dialog1 = ({show1, handleClose1, reload}) => {
function rerender() {
reload();
}
return (
<div>
<Modal show={show1} onHide={handleClose1}>
<Modal.Header closeButton>
<span className=" d-flex justify-content-center" style={{marginLeft: "150px"}}>
<img src={Stage1} class=" img-fluid d-block rounded " alt="nurse_image_1" style={{height: "165px"}}/>
</span>
</Modal.Header>
<Modal.Body className="conatainer-fluid m-auto">
<h4 className="font-weight-bold mx-3">
These symptoms are the sign of coronavirus.
Please call 9-1-1 or call the Emergency
Department for help!
</h4>
</Modal.Body>
<Modal.Footer className="d-flex justify-content-center mx-auto">
<ButtonBootstrap onClick={} variant="primary" size="lg" active> //want to rerender the parent component
Retake Self-Assessment
</ButtonBootstrap>
</Modal.Footer>
</Modal>
</div>
)
}
export default Dialog1
I have tried forceupdate() method but it didn't worked if someone can tell me better idea for this.
also i think history.goback will not be appropriate for this. I have tried to pass the method inside parent component to get called when the button inside child component is clicked.
I've hit a wall and have no clue what to do. I'm simply trying to close my bootstrap modal but it just won't close. It opens fine but again it just won't close. I've tried so many ways to rectify this that there won't be enough space on this post to list all my attempts.
What am I doing wrong and how can I fix this?
Here's App.js:
import React, { Component } from 'react';
import Product from './Product';
import { ProductConsumer } from "../context";
import TitleBody from "./TitleBody";
import AboutButton from "./AboutButton";
import AboutButtonModal from "./AboutButtonModal";
export default class App extends Component {
constructor(props) {
console.log("Props - ", props);
super(props);
this.state = {
modalVisible: false
};
this.openModal = this.openModal.bind(this);
}
openModal() {
console.log("Open modal called ", this.state.modalVisible);
const modalVisible = !this.state.modalVisible;
this.setState({
modalVisible
}, console.log(this.state.modalVisible));
}
render() {
let styles = this.state.modalVisible
? { display: "block" }
: { display: "none" };
return (
<React.Fragment>
<div className="py-5">
<div className="container">
<TitleBody name="Welcome to" title="Cruskip"/>
<AboutButtonModal show={this.state.modalVisible} onClick={this.openModal} style={styles}/>
<AboutButton onClick={this.openModal}/>
</div>
</div>
</div>
</React.Fragment>
);
}
}
Here's AboutButtonModal.js:
import React from 'react';
import './AboutButtonModal.scss';
const Modal = ({ handleClose, show, children}, props) => {
const showHideClassname = show ? "modal display-block" : "modal display-none";
return(
<div className={showHideClassname} style={props.style}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button
type="button"
onClick={props.onClick}
className="close"
>
×
</button>
<h4 className="modal-title">Modal Header</h4>
</div>
<div className="modal-body">
<p>Some text in the modal.</p>
</div>
<div className="modal-footer">
<button
onClick={props.onClick}
type="button"
className="btn btn-default"
>
Close
</button>
</div>
</div>
</div>
</div>
);
};
export default Modal;
Here's AboutButton.js:
import React from 'react';
import './AboutButton.scss';
const AboutButton = (props) => {
return(
<div className="row">
<button className="about-btn" type="button" onClick={props.onClick}>
About Us
</button>
</div>
);
};
export default AboutButton;
If you are using ({ handleClose, show, children }, props),It won't give you to access of props onClick function..
So to use props, just apply object destructing of props..Now,Your code will become like this...
const Modal = ({ handleClose, show, children,...props})