In react how do I get a modal to display in one component by clicking an icon in another?
I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import SvgIcon from '@material-ui/core/SvgIcon';
import ShoppingCart from '@material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Modal from '@material-ui/core/Modal';
import Button from '@material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
reactjs
add a comment |
I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import SvgIcon from '@material-ui/core/SvgIcon';
import ShoppingCart from '@material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Modal from '@material-ui/core/Modal';
import Button from '@material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
reactjs
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07
add a comment |
I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import SvgIcon from '@material-ui/core/SvgIcon';
import ShoppingCart from '@material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Modal from '@material-ui/core/Modal';
import Button from '@material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
reactjs
I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import SvgIcon from '@material-ui/core/SvgIcon';
import ShoppingCart from '@material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import Modal from '@material-ui/core/Modal';
import Button from '@material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
reactjs
reactjs
asked Nov 21 '18 at 16:43


frootloopsfrootloops
528
528
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07
add a comment |
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07
add a comment |
1 Answer
1
active
oldest
votes
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer
... The OuterContainer is also the one which will handleTheClickEvent
which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent
's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen
and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal
/closeModal
defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider>
component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore()
this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch()
they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416812%2fin-react-how-do-i-get-a-modal-to-display-in-one-component-by-clicking-an-icon-in%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer
... The OuterContainer is also the one which will handleTheClickEvent
which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent
's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen
and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal
/closeModal
defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider>
component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore()
this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch()
they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
add a comment |
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer
... The OuterContainer is also the one which will handleTheClickEvent
which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent
's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen
and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal
/closeModal
defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider>
component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore()
this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch()
they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
add a comment |
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer
... The OuterContainer is also the one which will handleTheClickEvent
which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent
's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen
and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal
/closeModal
defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider>
component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore()
this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch()
they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer
... The OuterContainer is also the one which will handleTheClickEvent
which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent
's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen
and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal
/closeModal
defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider>
component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore()
this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch()
they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)
edited Dec 8 '18 at 15:14
answered Nov 21 '18 at 16:49
ZargoldZargold
706420
706420
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416812%2fin-react-how-do-i-get-a-modal-to-display-in-one-component-by-clicking-an-icon-in%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
have you tried my solution yet? let me know if you need me to use your actual Modal but I think you should be able to do it from there.
– Zargold
Nov 21 '18 at 19:13
Thanks Zargold. Sorry for the delayed response. I haven't tried to implement it yet, but I was thinking about just using redux like you said. I am building an e-commerce shop with firebase, so I think redux will come in handy for keeping track of the merch as well as modals and other dynamic content.
– frootloops
Nov 22 '18 at 2:07