I'm new to React and Web-Dev in general. I'm creating a custom context menu when a user right-clicks on the web-app I'm creating. A modal should pop-up when you click on the custom context menu. However, the modal isn't showing up. What am I doing wrong?
Here is the code for the context menu:
class ContextMenu extends React.Component {
constructor(props){
super(props);
this.state = {
xPos: "0px",
yPos: "0px",
showMenu: false,
}
}
componentDidMount() {
document.addEventListener("click", this.handleClick);
document.addEventListener("contextmenu", this.handleContextMenu);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClick);
document.removeEventListener("contextmenu", this.handleContextMenu);
}
handleClick = (e) => {
if (this.state.showMenu) this.setState({ showMenu: false });
}
handleContextMenu = (e) => {
e.preventDefault();
this.setState({
xPos: `${e.pageX}px`,
yPos: `${e.pageY}px`,
showMenu: true,
})
}
alertClicked = () => {
<Modal show = {true}>
<Modal.Header closeButton>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
</Modal>
}
render() {
const { showMenu, yPos, xPos } = this.state;
if (showMenu) {
return (
<div
className="menu-container"
style={{
top: yPos,
left: xPos,
zIndex: 9,
position: "absolute",
}}>
<ListGroup>
<ListGroup.Item action onClick = {this.alertClicked}>
Show Modal
</ListGroup.Item>
</ListGroup>
</div>
);
} else return null;
}
}
This is the article I'm following to create the context menu.
You can't return JSX from an event handler like that and expect it do be rendered with the JSX you are returning from the function body.
Move the modal JSX into the render
lifecycle method, replacing the "Show Modal" text.
class ContextMenu extends React.Component {
constructor(props) {
super(props);
this.state = {
xPos: "0px",
yPos: "0px",
showMenu: false
};
}
componentDidMount() {
document.addEventListener("click", this.handleClick);
document.addEventListener("contextmenu", this.handleContextMenu);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClick);
document.removeEventListener("contextmenu", this.handleContextMenu);
}
handleClick = (e) => {
if (this.state.showMenu) this.setState({ showMenu: false });
};
handleContextMenu = (e) => {
e.preventDefault();
this.setState({
xPos: `${e.pageX}px`,
yPos: `${e.pageY}px`,
showMenu: true
});
};
alertClicked = () => {
// do something when clicked?
};
render() {
const { showMenu, yPos, xPos } = this.state;
if (showMenu) {
return (
<div
className="menu-container"
style={{
top: yPos,
left: xPos,
zIndex: 9,
position: "absolute"
}}
>
<ListGroup>
<ListGroup.Item action onClick={this.alertClicked}>
<Modal show={true}>
<Modal.Header closeButton>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
</Modal>
</ListGroup.Item>
</ListGroup>
</div>
);
} else return null;
}
}
It occurs to me that you may be trying to open the modal from the context menu. In this case add a separate showModal
state that is toggled true
in the alertClick
handler. Use the showModal
state to control the open
prop of Modal
.
class ContextMenu extends React.Component {
constructor(props) {
super(props);
this.state = {
xPos: "0px",
yPos: "0px",
showMenu: false
};
}
componentDidMount() {
document.addEventListener("click", this.handleClick);
document.addEventListener("contextmenu", this.handleContextMenu);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClick);
document.removeEventListener("contextmenu", this.handleContextMenu);
}
handleClick = (e) => {
if (this.state.showMenu) this.setState({ showMenu: false });
};
handleContextMenu = (e) => {
e.preventDefault();
this.setState({
xPos: `${e.pageX}px`,
yPos: `${e.pageY}px`,
showMenu: true,
showModal: false
});
};
alertClicked = () => {
this.setState({ showModal: true });
};
render() {
const { showMenu, yPos, xPos } = this.state;
if (showMenu) {
return (
<div
className="menu-container"
style={{
top: yPos,
left: xPos,
zIndex: 9,
position: "absolute"
}}
>
<ListGroup>
<ListGroup.Item action onClick={this.alertClicked}>
<Modal show={this.state.showModal}>
<Modal.Header closeButton>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
</Modal>
</ListGroup.Item>
</ListGroup>
</div>
);
} else return null;
}
}