In react how do I get a modal to display in one component by clicking an icon in another?












0















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;









share|improve this question























  • 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
















0















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;









share|improve this question























  • 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














0












0








0








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;









share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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



















  • 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












1 Answer
1






active

oldest

votes


















0














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>
</>
)








share|improve this answer

























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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>
    </>
    )








    share|improve this answer






























      0














      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>
      </>
      )








      share|improve this answer




























        0












        0








        0







        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>
        </>
        )








        share|improve this answer















        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>
        </>
        )






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 8 '18 at 15:14

























        answered Nov 21 '18 at 16:49









        ZargoldZargold

        706420




        706420
































            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

            Npm cannot find a required file even through it is in the searched directory