Ways to exclusively trigger the onclick function of the primary button when dealing with nested buttons in React.js

Let me elaborate on this issue. I have a List component from material-UI, with ListItem set to button=true which makes the entire item act as a button.

Within the ListItem, I have added a FontAwesomeIcon. To hide the button, I set its style to visibility: "hidden" and the Icon to visibility: "visible" so that it remains visible. (perhaps not the best practice, but couldn't think of another way at the moment).

Now, when someone clicks on the ListItem outside the Icon area, the onClick event of the ListItem is triggered - which is expected and good! However, when clicking on the Icon itself, both the onClick events of the "Icon button" and the ListItem are called - while this behavior is expected, it's not desired in my case.

Is there a way to bring the smaller "nested" button to the forefront of the parent button so that only its event is triggered?

If not, is there a way for the parent onClick event to detect whether it was clicked within the Icon area so that different functions can be called based on the click location?

I am open to any other suggestions as I am new to react and web development in general, and I want to learn and implement best practices solutions.

Thank you in advance :)

Answer №1

This relates to handling events in JavaScript. You can utilize the event.stopPropagation() method to prevent an event from propagating up the DOM tree. Learn more about event.stopPropagation() here.

Check out this React example below:

import React from "react";
import "./styles.css";

export default function App() {
  const parentButtonHandler = () => {
    console.log("parent");
  };
  const childButtonHandler = (e) => {
    console.log("child");
    e.stopPropagation();
  };

  return (
    <div className="App">
      <button onClick={parentButtonHandler}>
        Hello CodeSandbox
        <button onClick={childButtonHandler}>
          Start editing to see some magic happen!
        </button>
      </button>
    </div>
  );
}

Answer №2

It seems like the issue you're experiencing is due to event bubbling. For more detailed information, check out this resource: https://javascript.info/bubbling-and-capturing A possible solution is to utilize event.stopPropagation() within the click event handler for the "Icon button", preventing the event from bubbling up to the ListItem parent element.

Answer №3

Using nested buttons in your layout may not be the best idea as it can make it harder to support and result in a messy design.

If you're looking for alternative approaches, consider the following options:

  1. Having two separate buttons within your ListItem component
export const Comp = () => {
  return (
   <ListItem>
    <button onClick={handleOnMainClick}>mainButton</button>
    <button onClick={handleOnSecondClick}>secondButton</button>
   </ListItem>
  )
}

This method works well if your buttons are meant to be on either the left or right side only.

  1. If you need to position your functional button anywhere on the screen, you can use CSS positioning
export const Comp = () => {
  return (
   <ListItem styles={{position: 'relative'}}>
    <button onClick={handleOnMainClick}>mainButton</button>
    <button 
      styles={{position: 'absolute', top: '50%', left: '50%'}} 
      onClick={handleOnSecondClick}>
         secondButton
     </button>
   </ListItem>
  )
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can the functions passed into Material-UI withStyles() be relocated within the component?

Attempting to break down the components of my dashboard into smaller parts has proven challenging due to their dependence on drawerWidth. Initially, I considered moving drawerWidth into the state so it can be passed down to each component. However, I encou ...

How can I asynchronously parse JSON data from a URL on a Windows phone and display it in a

As an Android developer exploring the world of Windows Phone for the first time, I came across this resource on how to handle list boxes in Windows Phone 7/8. However, my challenge now is parsing JSON from a URL instead of XML as shown in the example. Whil ...

Comparing React state and props in intricate configurations

I recently completed a project where my React application fetches data from an API. Below is the mockup I used: List of objects -- Object --- Select field This is the code for my OrdersList.jsx: import React from 'react'; import Order from & ...

How can express.js be properly installed using typescript?

Currently, I am in the process of setting up a new project that involves using express.js with typescript integration. Would it suffice to just install @types/express by running the following command: npm install @types/express Alternatively, do I also ...

ERROR: The value property is undefined and cannot be read in a ReactJS component

Can someone help me with the error I'm encountering in the handleChange function? I'm not sure what the issue could be. const [testState, setTestState] = useState({ activeStep:0, firstName: '', lastName: '&apos ...

retrieve the information from a specific field within the store and store it in an array

Perhaps this is a question that pertains to using pure JavaScript, but for some reason I can't seem to figure it out. I am currently working on extjs4.2 using Sencha Architect and have received a JSON response from the server in the following format: ...

Using AJAX to transform octet-stream into typed array (Float64Array)

I can't seem to figure out where I'm going wrong here. My attempt involves converting a binary stream obtained from an AJAX request into an array of doubles using JavaScript. Here is some of my code: The PHP script on my server returns an octet-s ...

Filters in VueJs do not produce any results

Example of Basic Code <!DOCTYPE html> <html> <head> <title>My First Vue Application</title> <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b9cfcc ...

When an SVG image is embedded, its color may not change even after being converted to an inline SVG

I've inserted an SVG using an img tag. When hovering over it, I want the fill color of the SVG to change. I attempted to convert the SVG to inline SVG following this method, but it doesn't seem to be working as expected. No console errors are b ...

Omit the <span> tag when exporting to XLS format

Currently, I have a functioning jQuery DataTable that utilizes the TableTools plug-in and includes <span> elements in one of the columns for each row. When clicking on the export button, my goal is to exclude or hide the <span> elements from t ...

Applying CSS to Dynamic JavaScript Elements: A Guide to Styling Without In-line Code

I'm a beginner in web development and I've been experimenting with applying styles to dynamically generated div elements using JavaScript. So far, I've only been able to manually add inline styling through this function: function applyStyle( ...

Height in Material-UI CardMedia

I'm having trouble adjusting the height of the image inside the CardMedia component. I have defined the styles like this: const style = { height: 32, }; and I am applying it to the CardMedia component like so: <CardMedia overlay={<CardTi ...

The use of the .reset() function in typescript to clear form data may lead to unexpected

I've been trying to use document.getelementbyID().reset(); to reset form values, but I keep running into an error in TypeScript. Property 'reset' does not exist on type 'HTMLElement'. Here's how I implemented it: const resetB ...

Filtering records in Sails.js through route parameters

As a newcomer to Sails.js, I'm delving into its capabilities and workings. My scenario involves three interconnected models through associations: Series.js -> Season.js -> and Episode.js. Series.js module.exports = { attributes: { /* ...

Ways to eliminate bottom margin of text area in vuetify

Greetings, I am facing an issue with the following code snippet: <v-text-field :rules="rules" v-model="exam.title" class="exam-title ma-0 pa-0" ></v-text-field> <v-text-field class="exam-title ma-0 pa-0"></v-text-field& ...

Adjust the value based on selection

I aim to display another div when either the Full Time or Part Time option is selected. Additionally, I would like to calculate a different value for each option; if 'Part Time' is chosen, PrcA should change to PrcB. Here is the code snippet tha ...

WordPress REST API - Issue with New Category returning undefined, yet still able to be accessed

Currently, I am utilizing the WordPress REST API and have successfully created a new category. However, when making queries to the API, it is returning undefined for that particular category. Upon visiting: /wp-json/wp/v2/categories, category 17 does not ...

What are the advantages of going the extra mile to ensure cross-browser compatibility?

It's fascinating how much effort is required to ensure web applications work seamlessly across all browsers. Despite global standards like those set by W3C, the development and testing process can be quite laborious. I'm curious why all browsers ...

How can you include a comma between two objects within a string, excluding the last object, using JavaScript?

I have a string object stored in a variable passed from another class. My question is how can I add a comma between two objects, excluding the last object? Below is my code snippet: { "id":"57e4d12e53a5a", "body":"asdas", "publishe ...

Including a .css file in ejs

I'm currently developing an application using Node.js (express) with EJS, and I'm facing an issue while including a .css file in it. When I tried the same setup as a standalone HTML-CSS project, it worked perfectly fine. How can I include the CSS ...