How to use multiple material ui dialog with React? - javascript

I want to use two dialog in sign up page and login page.
the implement that I want to do are signup screen showing up when click to sign up button on the Top page, and login screen showing up when click to login Button on signup page.
I wrote open state on App.js.
but the trouble is when it's written in App.js, two of modal open..
Does anyone know how to settle it?
App.js
const App = () => {
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Top handleClickOpen={handleClickOpen}/>
<SignupModal open={open} handleClose={handleClose} />
<LoginModal open={open} handleClose={handleClose} />
</div>
)
Top.js
const Top = (props) => {
const classes = useStyles();
return (
<React.Fragment>
<div style={style}>
<Button variant="outlined" className={classes.loginButton} onClick={props.handleClickOpen}>
Login
</Button>
</div>
<h1>Toppage</h1>
</React.Fragment>
);
}
SignupModal.js
const SignupModal = (props) => {
return (
<div>
<Dialog
open={props.open}
onClose={props.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title" className={classes.title}>Sign up</DialogTitle>
<DialogContent className={classes.content}>
<div className={classes.text}>
<TextField id="standard-basic" label=“name” fullWidth/>
<TextField id="standard-basic" label=“email” fullWidth/>
<TextField id="standard-basic" label=“password” fullWidth/>
<TextField id="standard-basic" label=“pass”word fullWidth/>
</div>
</DialogContent>
<p className={classes.toLogin}>to Login</p>
<DialogActions>
<Button onClick={props.handleClose} className={classes.signUpButton}>
Send
</Button>
</DialogActions>
</Dialog>
</div>
);
}
LoginModal.ls
const LoginModal = (props) => {
return (
<div>
<Dialog
open={props.open}
onClose={props.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title" className={classes.title}>Login</DialogTitle>
<DialogContent className={classes.content}>
<div className={classes.text}>
<TextField id="standard-basic" label=“name” fullWidth/>
<TextField id="standard-basic" label=“pass”word fullWidth}/>
</div>
</DialogContent>
<DialogActions>
<Button onClick={props.handleClose} className={classes.signUpButton}>
Login
</Button>
</DialogActions>
</Dialog>
</div>
);
}
export default LoginModal

You are sharing the state on both of your modals that's why.
The solution is simple, have 2 states; one that will determine if SignupModal is opened or not and another one for LoginModal.
const App = () => {
const [openLogin, setOpenLogin] = useState(false);
const [openSignup, setOpenSignup] = useState(false);
return (
<div>
<Top
onClickLogin={() => setOpenLogin(true)}
onClickSignup={() => setOpenSignup(true)}
/>
<SignupModal open={openLogin} handleClose={() => setOpenLogin(false)} />
<LoginModal open={openSignup} handleClose={() => setOpenSignup(false)} />
</div>
);
};
const Top = (props) => {
return (
<React.Fragment>
<div>
<Button
variant="outlined"
className={classes.loginButton}
onClick={props.onClickLogin}
>
Login
</Button>
<Button
variant="outlined"
className={classes.loginButton}
onClick={props.onClickSignup}
>
Signup
</Button>
</div>
<h1>Toppage</h1>
</React.Fragment>
);
};

Related

How to edit a row in Material UI Table?

I trying to make a crud table using material UI,but as my first react project I have some issues.I don't know how to make the edit.I take the data to the edit-modal but I don't know how to make the update in the table.
export default function ResponsiveDialog({dataParent1,dataParent2}) {
const [open, setOpen] = React.useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('md'));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" color='success' onClick={handleClickOpen}>
Edit
</Button>
<Dialog
fullScreen={fullScreen}
open={open}
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
>
<DialogTitle id="responsive-dialog-title">{"Edit Post"}
</DialogTitle>
<DialogContent>
<Divider variant="middle"/>
<DialogContentText>
Title
</DialogContentText>
<TextField id="outlined-basic" defaultValue={dataParent1} style = {{width: 500}} variant="outlined" />
<DialogContentText>
Description
</DialogContentText>
<TextField id="outlined-basic" multiline rows={4} defaultValue={dataParent2} style = {{width: 500}} variant="outlined" />
</DialogContent>
<DialogActions>
<Button autoFocus variant="outlined" color='error' onClick={handleClose}>
Exit
</Button>
<Button color='success' variant="outlined" onClick={handleClose} autoFocus>
Save Changes
</Button>
</DialogActions>
</Dialog>
</div>
);}
Codesandbox:
https://codesandbox.io/s/angry-panka-7wd7ye?file=/src/App.js

Transform button into text after condition is true

I'm using the AppBar component of material-ui library, I added a button, I'd say it's hardcoded in the AppBar, I'm trying to transform this button to just a text in the AppBar, but I got nothing.
How can I transform the button in the AppBar to just text?
App.js:
const connectWalletChecker = () => {
return(
<div>
<SearchAppBar id='walletButton' apptitle={apptitle} color='primary' variant='contained' text='Connect Wallet' handle={connectWalletPressed}/>
</div>
)
}
const AlreadyConnected = () => {
return(
<div>
<SearchAppBar id='walletButton' apptitle={apptitle} color='primary' variant='contained' text={walletAddress} handle={null}/>
</div>
)
}
return(
<div>
{walletAddress ? AlreadyConnected() : connectWalletChecker()}
</div>
)
};
AppBar:
<Button id={props.id} color={props.color} variant={props.variant}
href="#contained-buttons" onClick={props.handle}>{props.text}</Button>
Full code on Github.
use variant="text" instead of variant="contained" for transforming button into text.
your code will be :
const connectWalletChecker = () => {
return(
<div>
<SearchAppBar id='walletButton' apptitle={apptitle} color='primary' variant='text' text='Connect Wallet' handle={connectWalletPressed}/>
</div>
)
}
const AlreadyConnected = () => {
return(
<div>
<SearchAppBar id='walletButton' apptitle={apptitle} color='primary' variant='text' text={walletAddress} handle={null}/>
</div>
)
}
return(
<div>
{walletAddress ? AlreadyConnected() : connectWalletChecker()}
</div>
)
};

How can I call "useSate(false)" in React from a nested component?

How can I call "useSate(false)" in React from a nested component?
I would like to close the sidebar when one of the sidebar items is clicked. For that I need to call the onclick function setOpen(true) from the parent component.
function SearchDropdown() {
const [open, setOpen] = useState(false);
return (
<>
<div className="searchIcon" onClick={() => setOpen(!open)}><img src="./assets/img/SearchN.jpg" alt=" " /><p>Search</p></div>
{open && <>
<div className="searchBarDropdown"><SearchBar></SearchBar></div>
<div onClick={() => setOpen(!open)} className="searchBarDropdownX"></div>
</>}
</>
);
}
function MenuSidebar() {
const [open, setOpen] = useState(false);
return (
<>
<div className="logo" onClick={() => setOpen(true)}><p>LOgo</p><img className="dropdown" src="./assets/img/Dropdown.png" alt=">" /></div>
{open && <>
<div className="menuSidebar">
<h3 className="backwardsSection" onClick={() => setOpen(false)}>🠔 Go Back</h3>
<MenuSidebarItems />
<h3 className="sidebarTopics">Topics</h3>
<TopicItems />
</div>
<div className="menuSidebarSpacing" onClick={() => setOpen(false)}></div>
</>}
</>
);
}
function MenuSidebarItems() {
return (
<>
<MenuSidebarItem leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Home</MenuSidebarItem>
<MenuSidebarItem leftIcon={ <HomeIcon /> }>Dashboard</MenuSidebarItem>
<MenuSidebarItem leftIcon={ <HomeIcon /> }>Shop</MenuSidebarItem>
<MenuSidebarItem leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Projects</MenuSidebarItem>
<MenuSidebarItem leftIcon={ <HomeIcon /> }>About</MenuSidebarItem>
</>
);
}
function MenuSidebarItem(props) {
const navigate = useNavigate();
return (
<button className="menuItem" onClick={() => {
navigate("/" + props.children.toString().toLowerCase());
}}>
<span className="leftIcon">{props.leftIcon}</span>
{props.children}
<span className="rightIcon">{props.rightIcon}</span>
</button>
);
}
Thanks, Martin
You need to pass the setState that close the navbar as props to the component that display the menu.
function SearchDropdown() {
const [open, setOpen] = useState(false);
return (
<>
<div className="searchIcon" onClick={() => setOpen(!open)}><img src="./assets/img/SearchN.jpg" alt=" " /><p>Search</p></div>
{open && <>
<div className="searchBarDropdown"><SearchBar></SearchBar></div>
<div onClick={() => setOpen(!open)} className="searchBarDropdownX"></div>
</>}
</>
);
}
function MenuSidebar() {
const [open, setOpen] = useState(false);
return (
<>
<div className="logo" onClick={() => setOpen(true)}><p>LOgo</p><img className="dropdown" src="./assets/img/Dropdown.png" alt=">" /></div>
{open && <>
<div className="menuSidebar">
<h3 className="backwardsSection" onClick={() => setOpen(false)}>🠔 Go Back</h3>
<MenuSidebarItems setOpen={setOpen}/>
<h3 className="sidebarTopics">Topics</h3>
<TopicItems />
</div>
<div className="menuSidebarSpacing" onClick={() => setOpen(false)}></div>
</>}
</>
);
}
function MenuSidebarItems(props) {
const {setOpen} = props
return (
<>
<MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Home</MenuSidebarItem>
<MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>Dashboard</MenuSidebarItem>
<MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>Shop</MenuSidebarItem>
<MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> } rightIcon={ <HomeIcon></HomeIcon> }>Projects</MenuSidebarItem>
<MenuSidebarItem setOpen={setOpen} leftIcon={ <HomeIcon /> }>About</MenuSidebarItem>
</>
);
}
function MenuSidebarItem(props) {
const navigate = useNavigate();
const {setOpen} = props
return (
<button className="menuItem" onClick={() => {
setOpen={flase}
navigate("/" + props.children.toString().toLowerCase());
}}>
<span className="leftIcon">{props.leftIcon}</span>
{props.children}
<span className="rightIcon">{props.rightIcon}</span>
</button>
);
}

how to open modal2 from a button of modal1 in react

I have two modals one is Login modal and another is Signup modal now I want to open signup modal by clicking on a button which is present in login modal, I tried many different ways but not able to achieve it, also I tried to make a signupModalSwitch with useReducer and by making different function calls but it was saying against hooks rule, I am very new to react not able to figure out how to do it. Thanks in Advance :)
modal1 ->
function LoginModal() {
const [open, setOpen] = React.useState(false);
const handleOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button
onClick={handleOpen}
variant="outlined"
className={classNames(
classes.textNeonGreen,
classes.outlinedNeonGreen,
classes.navButton
)}
classes={{ disabled: classes.disabled }}
>
<Typography noWrap>Login</Typography>
</Button>
<Modal
className={classes.modal}
open={open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={open}>
<LoginCard LoginClose={handleClose} />
</Fade>
</Modal>
</div>
);
}
function LoginCard({ LoginClose }) {
return (
<Card className={classes.modalCard}>
<span>
<button
onClick={LoginClose}
type="button"
className="close px-2 pt-2"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</span>
<CardContent className={classes.modalCardContent}>
<Typography variant="h4" className={classes.modalHeading}>
<b>Login</b>
</Typography>
<Account>
<Login />
</Account>
<div>
<Grid
container
direction="column"
justify="center"
alignItems="center"
>
<p className="mb-2 mt-4 text-center">
Don't have Account?
</p>
//###### BY CLICKING THIS BUTTON I WANT TO OPEN MY SIGNUP MODAL #######//
<button
className="btn btn-outline-success btn-block btn-md"
onClick={() => {
LoginClose();
signupModalSwitch(null,{type:'open'})
}
}
>
Signup
</button>
</Grid>
</div>
</CardContent>
</Card>
);
}
MODAL2 ->
function signupModalSwitch(state, action){
switch(action.type){
case 'open':
return { open: true }
case 'close':
return { open: false }
default:
console.log(action);
}
}
function SignupModal() {
const classes = useStyles();
const [state, dispatch] = useReducer(signupModalSwitch, { open: false })
function handleOpen() {
dispatch({type: "open"});
}
function handleClose() {
dispatch({type: "close"});
};
return (
<div>
<Button
onClick={handleOpen}
variant="outlined"
className={classNames(
classes.textNeonGreen,
classes.outlinedNeonGreen,
classes.navButton
)}
classes={{ disabled: classes.disabled }}
>
<Typography noWrap>Signup</Typography>
</Button>
<Modal
className={classes.modal}
open={state.open}
onClose={handleClose}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={state.open}>
<SignupCard signupClose={handleClose} />
</Fade>
</Modal>
</div>
);
}
function SignupCard({ signupClose }) {
return (
<Card className={classes.modalCard}>
<span>
<button
onClick={signupClose}
type="button"
className="close px-2 pt-2"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</span>
<CardContent className={classes.modalCardContent}>
<Typography variant="h4" className={classes.modalHeading}>
<b>Signup</b>
</Typography>
<Signup />
</CardContent>
</Card>
);
}
A better way to do this would be to create a container and move all the logic to the container. Your login and sign up modals should be dumb components, i.e, do not maintain the state in these components.
In your container, keep two states, openLoginModal and openSignupModal.
const [openLoginModal, setOpenLoginModal] = useState(false)
const [openSignupModal, setOpenSignupModal] = useState(false)
You can pass these as props to your login and signup components. When you click the button in the login modal, you will need one more function that closes login modal and opens sign up modal. You can pass this as prop as well.
const onSignupButtonClick = () => {
setOpenLoginModal(false)
setOpenSignupModal(true)
}
You can conditionally render login and signup modal based on the state values.

modal not shown in storybook

I have a working modal component which i need to show in storybook as well. It depends on the props
to show and close. For example, if i need to show modal i would have to do the following
const Demo = () => {
const [open, setOpen] = useState(false)
return (
<>
<button onClick={() => setOpen(true)}>Open Modal</button>
<Modal open={open} onClose={() => setOpen(false)}>
<Modal.Header>Modal Header goes here</Modal.Header>
<Modal.Content>Modal Content goes here</Modal.Content>
<Modal.Footer>Modal Footer goes here</Modal.Footer>
</Modal>
</>
)
}
I am using ReactDOM.createPortal to render modal so for this i have created a div element with an id
modal and inside it another div element is created where the modal appears. For such i have created a
story of modal as follow
storiesOf('Modals', module)
.addDecorator(storyFn => (
<>
<div id="modal">
<div>{storyFn()}</div>
</div>
</>
))
.addDecorator(withKnobs)
.add('Modals - Basic', () => (
<>
<button type="button">Show Modal</button>
<Modal open={boolean('open', false)}>
<Modal.Header>Modal Header goes here</Modal.Header>
<Modal.Content>Modal Content goes here</Modal.Content>
<Modal.Footer>Modal Footer goes here</Modal.Footer>
</Modal>
</>
))
My modal is created in the following way
const el = document.createElement('div')
const modal = document.getElementById('modal')
return ReactDOM.createPortal(
<>
<Backdrop onClick={e => closeModal(e)}>
<ModalBox>
<Wrapper position={position} {...props}>
{children}
<CloseIcon icon={faTimesCircle} />
</Wrapper>
</ModalBox>
</Backdrop>
</>,
el,
)

Categories