React es6 es2015 modal popup - modal-dialog

I'm very new to React and ES6. I'm building a small application using React and I'm following ES6 standard. Now I need to open a modal window on a button click.
I tried react-bootstrap modal and skylight. But did not find much luck.
Can anyone suggest the best way of opening/closing modal along with a callback.
Thanks in advance.

I've put together an example to illustrate how you might go about this, making use of the parent/child relationship and passing down a callback.
The scenario is basically:
There is a parent <App /> component
It can show a <Modal /> component
<App /> controls whether the <Modal /> is open or not
<App /> passes its child, <Modal />, a callback to "closeModal"
See this JSBin example for the full solution in action: http://jsbin.com/cokola/edit?js,output
And a visual summary:
<Modal /> is just a "dumb" component. It does not "control" whether it is open or not. This is up to the parent <App />. The parent informs it of how to close itself via passing down a callback this.props.closeModal
class Modal extends React.Component {
render() {
const { closeModal } = this.props;
return (
<div className="jumbotron" style={{position: 'absolute', width: '100%', top: 0, height: 500}}>
<h1>Some Modal</h1>
<button
className="btn btn-md btn-primary"
onClick={closeModal}
>Close Modal</button>
</div>
)
}
}
<App /> is aware of the open/closed state and controls its child, <Modal />
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
};
}
_openModal() {
this.setState({modalOpen: true});
}
_closeModal() {
this.setState({modalOpen: false});
}
render() {
const { modalOpen } = this.state;
return (
<div>
<button
className="btn btn-md btn-primary"
onClick={this._openModal.bind(this)}
>Open Modal</button>
{/* Only show Modal when "this.state.modalOpen === true" */}
{modalOpen
? <Modal closeModal={this._closeModal.bind(this)} />
: ''}
</div>
);
}
}

Related

Antd Modal+Carousel+Form shudders for 10ms

During opening antd modal I can see for 10ms that my modal is increased and displays not the first page of the carousel inside.
Here I have attached a Json file, which you can play in your Chrome DevTools (F12 -> Performance -> Load profile). Described problem appears on 1150ms. Here is the link to the codesanbox where you can play with my code. I found that the modal increases because my form layout equal to "vertical", but I still didn't get why the last page of my carousel appears first. I am thinking of some hooks in React like useLayoutEffect to render it correctly, however it seems to my as a antd bug, or my mistake somewhere and I don't want to overload my code with useless hooks.
Here is the code for that who won't open codesanbox:
import "./styles.css";
import React, { useState, useRef } from "react";
import { Modal, Carousel, Form, Button, Input, Image } from "antd";
export default function App() {
const [modal, setModal] = useState<boolean>(false);
const [pageOneForm] = Form.useForm();
const [pageTwoForm] = Form.useForm();
return (
<>
<Button onClick={() => setModal(true)}> open </Button>
<Modal
width={500}
centered
closable={false}
title={"Title of my modal"}
open={modal}
onCancel={() => setModal(false)}
okButtonProps={{ style: { display: "none" } }}
>
<Carousel dotPosition="top" swipeToSlide draggable arrows>
<div>
<img alt="card1" src="card1.png" className="card" />
<Form
form={pageOneForm}
layout="vertical" //it makes my modal huge for few ms
>
<Form.Item
label="Some input for 1 page"
name="carteVitale"
rules={[{ required: true, message: "" }]}
>
<Input />
</Form.Item>
</Form>
</div>
<div>
<img alt="card2" src="card2.png" className="card" />
<Form form={pageTwoForm} layout="vertical">
<Form.Item
label="Some input for 2 page"
rules={[{ required: true, message: "" }]}
>
<Input />
</Form.Item>
</Form>
</div>
</Carousel>
</Modal>
</>
);
}
I expect to render this modal without unplanned modal shakes
UPDATE:
Size of modal can be fixed by adding two keys to Carousel component:
<Carousel
adaptiveHeight={false}
lazyLoad="progressive"
...
or by playing with css:
<Carousel
initialSlide={0}
lazyLoad="ondemand"
className="cards-container"
...
<Form.Item
className="no-wrap"
...
and css will looks like:
.cards-container {
animation: fadein 0.5s ease;
position: relative;
}
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.no-wrap label {
white-space: nowrap;
overflow: hidden;
}

How to send trigger onClick to child component in soldjs and display it in parent?

I was trying to take example from react but seem it doesn't work as I expected.
I am trying to open a modal when user click the button in parent component, but function to open modal is located in the child component.
Parent component just where i try to invoke a modal:
<label class="text-white m-5 p-1">
<input type="checkbox" checked={false} onChange={handleCheck} />
I have read and agree to the <button onClick={}>Privacy</button>
<Portal>
<TermsModal />
</Portal>
</label>
How to do that?
If you want the Modal component to control the state, instead of it being passed with props you can use this pattern:
const { Modal, openModal } = createModal();
return (
<>
<button type="button" onClick={openModal}>
open modal
</button>
<Modal />
</>
);
It may be weird at first, but it's really fun and powerful :)
https://playground.solidjs.com/anonymous/d3a74069-e3d4-4d3e-9fb2-bafc5d6f5bf5
Create a signal inside parent component and pass it to the child component. Bind the visibility of the modal window to the signal's value:
import { Component, createSignal, Show } from 'solid-js';
import { Portal, render } from 'solid-js/web';
const Modal: Component<{ show: boolean }> = (props) => {
return (
<Show when={props.show}>
<div>Modal Window</div>
</Show>
);
};
const App = () => {
const [show, setShow] = createSignal(false);
const toggleShow = () => setShow(prev => !prev);
return (
<div>
<div>Show: {show() ? 'true': 'false'} <button onClick={toggleShow}>Toggle Show</button></div>
<Portal><Modal show={show()} /></Portal>
</div>
)
};
render(() => <App />, document.body);
https://playground.solidjs.com/anonymous/adf9ba7a-3e1b-4ce9-92b2-e78ff3fa55ec
You can further improve your component by creating a close handler and passing it to the child component. Now, modal window can show a close button.
Also you can add an event handler to the document in order to close the window whenever Escape key is pressed:
import { Component, createSignal, onCleanup, onMount, Show } from 'solid-js';
import { Portal, render } from 'solid-js/web';
const Modal: Component<{ show: boolean, close: () => void }> = (props) => {
const handleKeydown = (event) => {
if (event.key === 'Escape') {
props.close();
}
};
onMount(() => {
document.addEventListener('keydown', handleKeydown);
});
onCleanup(() => {
document.removeEventListener('keydown', handleKeydown);
});
return (
<Show when={props.show}>
<div>Modal Window <button onclick={props.close}>close</button></div>
</Show>
);
};
const App = () => {
const [show, setShow] = createSignal(false);
const close = () => setShow(false);
const toggleShow = () => setShow(prev => !prev);
return (
<div>
<div>Show: {show()} <button onClick={toggleShow}>Toggle Show</button></div>
<Portal><Modal show={show()} close={close} /></Portal>
</div>
)
};
render(() => <App />, document.body);
https://playground.solidjs.com/anonymous/0ae98cf1-19d6-487f-80dc-72d3c2e554dc
You can use a state in the parent component to keep track of whether the modal should be open or closed, and pass a function as a prop to the child component that updates that state:
const [isModalOpen, setIsModalOpen] = React.useState(false);
const handleButtonClick = () => {
setIsModalOpen(true);
};
return (
<div>
<label className="text-white m-5 p-1">
<input type="checkbox" checked={false} onChange={handleCheck} />
I have read and agree to the <button onClick={handleButtonClick}>Privacy</button>
<Portal>
<TermsModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} />
</Portal>
</label>
</div>
);
// Child component
const TermsModal = ({ isOpen, onClose }) => {
if (!isOpen) {
return null;
}
return (
<div className="modal">
{/* Modal content */}
<button onClick={onClose}>Close</button>
</div>
);
};

Material UI component written is function based component?

I am trying to use material ui component into react class based component material ui component demo everthing wrtten function based but we are written all project pages are class based very difficult to integrating material UI component
It is not difficult to integrate on class-based Components. yes, In Material UI doc all the things have integrated on functional-based Components with using Hooks. But you should have some Knowledge about hooks and state concepts then you can easily be integrated them.
for example:
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open alert dialog
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Use Google's location service?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Let Google help apps determine location. This means sending anonymous location
data to
Google, even when no apps are running.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Disagree
</Button>
<Button onClick={handleClose} color="primary" autoFocus>
Agree
</Button>
</DialogActions>
</Dialog>
</div>
);
}
So, this Dialog Code has written in functional Based Components But we can easily integrated on class based component Like:
export default class AlertDialog extends React.Components{
constructor(){
super(props)
this.state={
open:false
}
}
handleClickOpen = () => {
this.setState({open:true})
};
handleClose = () => {
this.setState({open:false})
};
render(){
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open alert dialog
</Button>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">{"Use Google's location service?"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Let Google help apps determine location. This means sending anonymous location
data to
Google, even when no apps are running.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Disagree
</Button>
<Button onClick={this.handleClose} color="primary" autoFocus>
Agree
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
So, just we should have Knowledge about basic React Concept and you can do this.

how to use material-ui Dialog PaperProps

I'm using v1.1.0 of material-ui in React 16.3.2. I'm trying to create a landing page similar to Showcase - Local Insights
where the dialog has opacity (Find foreclosures). I'm trying to use PaperProps for Dialog component described here Dialog doc
Here's a component I've created to try to do this.
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Button from '#material-ui/core/Button';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogTitle from '#material-ui/core/DialogTitle';
import ForwardIcon from '#material-ui/icons/Forward';
import Input from '#material-ui/core/Input';
import FormControl from '#material-ui/core/FormControl';
import Slide from '#material-ui/core/Slide';
const styles = theme => ({
dialogPaper: {
opacity: 0.5,
border: '#FF0000 1px solid',
},
button: {
margin: '30px'
}
});
function Transition(props) {
return <Slide direction="up" {...props} />;
}
class SignInDialog extends React.Component {
state = {
open: false,
username: ''
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
handleChange = name => event => {
this.setState({
[name]: event.target.value,
});
};
render() {
const { classes } = this.props;
return (
<div>
<Button variant="fab" color="primary" aria-label="add" className={classes.button} onClick={this.handleClickOpen}>
<ForwardIcon />
</Button>
<Dialog
PaperProps={styles.dialogPaper}
open={this.state.open}
TransitionComponent={Transition}
onClose={this.handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">WELCOME</DialogTitle>
<DialogContent>
<p>SIGN IN</p>
<FormControl className={classes.formControl}>
<Input
value={this.state.searchString}
onChange={this.handleChange('search')}
id="siginin-input"
placeholder="Enter your username"
/>
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary">
Continue
</Button>
</DialogActions>
</Dialog>
</div>
);
}
}
SignInDialog.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(SignInDialog);
I haven't been able to figure out how to get the Dialog to take the styles. What is needed to get PaperProps to work?
If you want to use PaperProps you have to specify the props of the Paperfor which you are applying style.
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>
You can also use classes property and override the style
<Dialog
classes={{paper:classes.dialogPaper}}
/>
The correct way to overide paper props is by using classNames
<Dialog
PaperProps={{ className: classNames(classes.dialogPaper) }}/>
<Dialog
PaperProps={{ classes: {root: classes.dialogPaper } }}
/>

react rerendering form causes focus/blur issue on state change

I have a form in a react component that has two change handlers, one for my two draftjs textareas, and one for my other text inputs:
onChangeEditor = (editorStateKey) => (editorState) => {
this.setState({ [editorStateKey]: editorState });
}
handleInputChange(event) {
event.preventDefault();
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
In my render method I have two views that I switch between depending on which view mode I am in, read or edit:
render () {
const Editable = () => (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" key="text01" name="title" defaultValue={this.state.title} onBlur={this.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.state.editorState1} onChange={this.onChangeEditor('editorState1')} name="text01"/>
<h4>Citat</h4>
<input type="text" key="text02" name="quote01" defaultValue={this.state.quote01} onBlur={this.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.state.editorState2} onChange={this.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.saveForm} />
</form>
</div>
);
const Readable = () => (
<div>
<h1 className="header66">{this.state.title}</h1>
<div className="text66">{this.state.text01}</div>
<div className="quote100">{this.state.quote01}</div>
<div className="text66">{this.state.text02}</div>
</div>
);
return (
<div>
{ this.props.isInEditMode ? <Editable /> : <Readable /> }
</div>
);
}
When I switch between inputs in my browser I have to click twice in order to get the focus on the right input.
I suspect that this is because a change is triggered on the "blur" event of each input, causing the form to rerender because state is changed. And when the form rerenders, it goes through the { this.props.isInEditMode ? <Editable /> : <Readable /> } which causes the input to lose focus.
The problem is that I don't know how to get around this.
I solved it myself.
It turns out that it was not a good idea to place the Editable and Readable inside of my component as I did. Instead I moved them out to their own components, and it works properly now.
class Editable extends React.Component {
render() {
return (
<div className="editor">
<form className="editor-inner">
<h3>Redigerar: Anbudsbrev</h3>
<h4>Rubrik</h4>
<input type="text" name="title" defaultValue={this.props.title} onChange={this.props.handleInputChange} />
<h4>Text 1</h4>
<RichEditor editorState={this.props.editorState1} onChange={this.props.onChangeEditor('editorState1')} name="text01" />
<h4>Citat</h4>
<input type="text" name="quote01" defaultValue={this.props.quote01} onChange={this.props.handleInputChange} />
<h4>Text 2</h4>
<RichEditor editorState={this.props.editorState2} onChange={this.props.onChangeEditor('editorState2')} name="text02" />
<EditorFooter {...this.props} submitForm={this.props.saveForm} />
</form>
</div>
);
}
};
class Readable extends React.Component {
render() {
return (
<div>
<h1 className="header66">{this.props.title}</h1>
<div className="text66">{this.props.text01}</div>
<div className="quote100">{this.props.quote01}</div>
<div className="text66">{this.props.text02}</div>
</div>
);
}
};