How To Add Click To Shop On Blog
According to Wikipedia, a context menu (also called right-click menu) is a menu in a graphical user interface (GUI) that appears upon user interaction, such as a right-click mouse operation. A context menu offers a limited set of choices that are available in the current state, or context, of the operating system or application to which the menu belongs.
If you right-click on your browser while visiting a website, you can see your OS's native context menu. You can save, print, create a QR code for the page, and much more. You should also see different options depending on where you are clicking on the page; if you highlight text, you can see options like copy, paste, and cut.
You may also see some customized context menus, like on email or list applications, and collaboration apps like Trello and Notion. These right-click menus give users more options while they are using the app.
In this post, we will explore how you can create a right-click menu in React, shortcuts to activate right-click menus, how to create a custom context menu hook, and some packages if you don't want to implement them yourself.
You can see the demo of the project below, and check out the full code on Github or the deployed website.
Creating a custom right-click menu
To create a right-click menu, we need to use the contextmenu
event listener. This event fires when the user attempts to open a context menu. It is typically triggered by clicking the right mouse button, or by pressing the context menu keyboard shortcut.
Creating a keyboard shortcut for a context menu
The keyboard shortcut for a context menu on Windows is Shift+F10. On Mac, you can use Ctrl+click or right+click; there doesn't seem to be a keyboard-only shortcut.
To create a keyboard shortcut for a context menu on a Mac, first go to System Preferences → Accessibility → Pointer Control → Alternate Control Methods → ✅ Enable alternate pointer actions. To use the shortcut use F12. If you don't know how to see the function keys because your Mac has a touchbar, check out this quick guide.
Building a context menu
To disable the default right-click menu, we need to use event.preventDefault()
:
document.addEventListener("contextmenu", (event) => { event.preventDefault() });
Next, we need to capture the x and y coordinates of the click and show the menu where the user clicks on the page. We can get pageX
and pageY
properties from the event object and apply coordinates to the top
and left
properties in CSS:
const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); document.addEventListener("contextmenu", (event) => { event.preventDefault() setAnchorPoint({ x: event.pageX, y: event.pageY }); });
We are using the useState
hook to manage anchor points and will update them when the user right-clicks on the page.
Customizing the context menu
Now we need to show the right-click menu to the user. The default value for the menu is false
, so we will be hiding it. When the user right-clicks, set setShow
to true
:
const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); const [show, setShow] = useState(false); document.addEventListener("contextmenu", (event) => { event.preventDefault() setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); });
We also need to use the useCallback
hook; this will return a memoized version of the callback that only changes if one of the dependencies has changed. This prevents unnecessary renders. React will keep only one copy of our function.
For this, we need to wrap everything inside a useCallback
function and pass the dependencies inside an array:
const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); const [show, setShow] = useState(false); document.addEventListener( "contextmenu", useCallback( (event) => { event.preventDefault(); setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); }, [setAnchorPoint, setShow] ) );
Utilizing useEffect
The last thing to take care of is the useEffect
hook when we are firing events on the DOM. This hook is used for side effects including API calls and DOM manipulation. When we listen for events, we also need to add a cleanup function.
When we run the code, it will clean up the old state first, then run the updated state. This will remove unnecessary behavior and prevent memory leaking issues.
We can do this by passing in a return function:
const handleContextMenu = useCallback( (event) => { event.preventDefault(); setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); }, [setAnchorPoint, setShow] ); useEffect(() => { document.addEventListener("contextmenu", handleContextMenu); } return () => { document.removeEventListener("contextmenu", handleContextMenu); });
Positioning the context menu
To show the menu we need to change the top and left position according to its x and y coordinates. We will put them in our App.js
component.
Here is the CSS code for the menu:
.menu { font-size: 14px; background-color: #fff; border-radius: 2px; padding: 5px 0 5px 0; width: 150px; height: auto; margin: 0; /* use absolute positioning */ position: absolute; list-style: none; box-shadow: 0 0 20px 0 #ccc; opacity: 1; transition: opacity 0.5s linear; }
To change the top and left position of the menu, we will dynamically update its position according to where the user clicked on the webpage. For this, add inline style to the menu
class and only show the menu when we have show
set to true
; otherwise don't show anything:
// App.js function App() { const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); const [show, setShow] = useState(false); const handleContextMenu = useCallback( (event) => { event.preventDefault(); setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); }, [setAnchorPoint, setShow] ); useEffect(() => { document.addEventListener("contextmenu", handleContextMenu); return () => { document.removeEventListener("contextmenu", handleContextMenu); }; }); return ( <div className="app"> <h1>Right click somewhere on the page..</h1> {show ? ( <ul className="menu" style={{ top: anchorPoint.y, left: anchorPoint.x }} > <li>Share to..</li> <li>Cut</li> <li>Copy</li> <li>Paste</li> <hr className="divider" /> <li>Refresh</li> <li>Exit</li> </ul> ) : ( <> </> )} </div> ); } export default App;
We also need to hide the menu when the user clicks on any menu items, or tries to click out of it. For this, we will have a conditional check: if the menu is shown, toggle the setShow
state to false
and hide the menu, otherwise don't do anything. This function is only updated whenever the show
state changes with the useCallback
hook.
Like we saw with the contextmenu
event, we are again dealing with the DOM, this time with the click
event.
Add this inside the useEffect
hook and remove the event listener in the return
function:
const handleClick = useCallback(() => (show ? setShow(false) : null), [show]); useEffect(() => { document.addEventListener("click", handleClick); return () => { document.removeEventListener("click", handleClick); }; });
That's it! Here is the full code:
import "./styles.css"; import { useCallback, useEffect, useState } from "react"; function App() { const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); const [show, setShow] = useState(false); // hide menu const handleContextMenu = useCallback( (event) => { event.preventDefault(); setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); }, [setAnchorPoint] ); const handleClick = useCallback(() => (show ? setShow(false) : null), [show]); useEffect(() => { document.addEventListener("click", handleClick); document.addEventListener("contextmenu", handleContextMenu); return () => { document.removeEventListener("click", handleClick); document.removeEventListener("contextmenu", handleContextMenu); }; }); return ( <div className="app"> <h1>Right click somewhere on the page..</h1> {show ? ( <ul className="menu" style={{ top: anchorPoint.y, left: anchorPoint.x }} > <li>Share to..</li> <li>Cut</li> <li>Copy</li> <li>Paste</li> <hr className="divider" /> <li>Refresh</li> <li>Exit</li> </ul> ) : ( <> </> )} </div> ); } export default App;
Creating a custom context menu hook
Until now, we have put all of our code inside App.js
. However, React is built on top of components, which means we can keep our code more modular.
Let's create some components. For our custom context menu, we will create a custom hook, and make use of it inside Menu
component. I will name the custom hook useContextMenu.js
and return show
and anchorPoint
from it.
The most important part of our custom hook is the return
statement. Here, we return whatever we want another component to have access to. We can return an array or an object.
If you return an array, we can name the returned values whatever we want outside the file. We don't need to keep the same name as what we have returned:
// useContextMenu.js import { useEffect, useCallback, useState } from "react"; const useContextMenu = () => { const [anchorPoint, setAnchorPoint] = useState({ x: 0, y: 0 }); const [show, setShow] = useState(false); const handleContextMenu = useCallback( (event) => { event.preventDefault(); setAnchorPoint({ x: event.pageX, y: event.pageY }); setShow(true); }, [setShow, setAnchorPoint] ); const handleClick = useCallback(() => (show ? setShow(false) : null), [show]); useEffect(() => { document.addEventListener("click", handleClick); document.addEventListener("contextmenu", handleContextMenu); return () => { document.removeEventListener("click", handleClick); document.removeEventListener("contextmenu", handleContextMenu); }; }); return { anchorPoint, show }; }; export default useContextMenu;
We will access our custom hook inside the Menu
component and pass the Menu
component inside the App.js
file:
// Menu.js import useContextMenu from "./useContextMenu"; const Menu = () => { const { anchorPoint, show } = useContextMenu(); if (show) { return ( <ul className="menu" style={{ top: anchorPoint.y, left: anchorPoint.x }}> <li>Share to..</li> <li>Cut</li> <li>Copy</li> <li>Paste</li> <hr /> <li>Refresh</li> <li>Exit</li> </ul> ); } return <></>; }; export default Menu;
Now, our App.js
is rendering a Menu
component and it looks much simpler:
// App.js import "./styles.css"; import Menu from "./Menu"; function App() { return ( <div className="app"> <h1>Right click somewhere on the page..</h1> <Menu /> </div> ); } export default App;
Adding Feather icons to the menu
Finally, I have used the react-feather
package to add Feather icons to the project.
All you need is import the package with npm install react-feather
. Import it at the top of your project with import * as Icon from "react-feather";
and access the icons like this:
<Icon.Share size={20} />
.
Conclusion and considerations
There are still other options if you don't want to implement a custom context menu yourself. One of them is Material UI. Material UI is a React UI framework, and it allows you to create different types of menus along with context menus.
Another option is the react-menu package. It offers unlimited levels of submenus, supports radio and checkbox menu items, supports context menus, and adheres to WAI-ARIA Authoring Practices.
If you are creating your own custom context menu, be sure to think about mobile interaction. Users may not be able to right-click if they are using a mobile phone. That's why you may need to think twice about why you really need a custom context menu. It can cause some bad experiences if the user just wants to see the default menu.
Full visibility into production React apps
Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you're interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.
LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your React apps — start monitoring for free.
How To Add Click To Shop On Blog
Source: https://blog.logrocket.com/how-to-create-a-context-menu-in-react/
Posted by: goblerespense.blogspot.com
0 Response to "How To Add Click To Shop On Blog"
Post a Comment