Changing the MaterialUI icon when it is clicked

Each item in a list has an "AddIcon". Upon clicking the icon, I want to replace it with a "BlockIcon" based on its unique "id".

import React from 'react'
import {List, ListItem} from '@material-ui/core'
import AddCircleIcon from '@material-ui/icons/AddCircleOutline'
import BlockIcon from '@material-ui/icons/BlockOutlined'

const CustomComponent = () => {
    const handleIconClick = (id) => {
        // logic to switch <AddCircleIcon /> with <BlockIcon /> using the specified "id"
    }
    return (
        <List component="nav">
            <ListItem>
                <ListItem button onClick={handleIconClick(101)}>
                    <AddCircleIcon /> 
                </ListItem>
            </ListItem>
        </List>
    )
}

export default CustomComponent

Upon clicking the icon, the expected behavior is for the AddIcon to be replaced with a BlockIcon.

Answer №1

It is recommended to create a state variable that will store the click status, allowing you to toggle between icons based on whether it has been clicked or not.

import React from 'react'
import {List, ListItem} from '@material-ui/core'
import AddCircleIcon from '@material-ui/icons/AddCircleOutline'
import BlockIcon from '@material-ui/icons/BlockOutlined'

const StackOverflow = () => {
    const [clicked, setClicked] = useState(false)
    const handleIconClick = (id) => {
         setClicked(true)
        // change <AddCircleIcon /> to <BlockIcon /> at "id"
    }
    return (
        <List component="nav">
            <ListItem>
                <ListItem button onClick={handleIconClick(101)}>
                    {clicked ? <BlockIcon /> : <AddCircleIcon /> }
                </ListItem>
            </ListItem>
        </List>
    )
}

export default StackOverflow

If you anticipate multiple items being clicked within a list, consider updating the structure as shown below:

const StackOverflow = () => {
    const [clicks, setClicks] = useState([])
     //add the id to the array of clicked items if it doesn't exist but if it does exist remove it. this makes sure that double clicking on an item brings it back to normal
    const handleIconClick = (id) => {
         let result =  clicks.includes(id)? clicks.filter(click => click != id): [...clicks, id]
         setClicks(result)
        // change <AddCircleIcon /> to <BlockIcon /> at "id"
    }
    return (
        <List component="nav">
            <ListItem>
                <ListItem button onClick={handleIconClick(101)}>
                    {clicks.includes(101) ? <BlockIcon /> : <AddCircleIcon /> }
                </ListItem>
            </ListItem>
        </List>
    )
}

export default StackOverflow

Keep in mind that when looping through items before displaying, ensure to pass the id dynamically rather than hardcoding the number in clicks.include(id) and handleIconClick(id).

Answer №2

Here is a functional example that includes a working demonstration (https://codesandbox.io/s/keen-kowalevski-cguvs?fontsize=14)

import React, { useState } from "react";
import ReactDOM from "react-dom";
import IconButton from "@material-ui/core/IconButton";
import AddCircleIcon from "@material-ui/icons/AddCircleOutline";
import BlockIcon from "@material-ui/icons/BlockOutlined";

function App() {
  const [clicked, setClicked] = useState();

  return (
    <IconButton onClick={() => setClicked(true)}>
      {clicked ? <BlockIcon /> : <AddCircleIcon />}
    </IconButton>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Answer №3

In the example below, everything is working as expected when interacting with the button

import React, { useState } from "react";
import ReactDOM from "react-dom";
import Button from "@material-ui/core/Button";
import Add from "@material-ui/icons/Add";
import Remove from "@material-ui/icons/Remove";

import "./styles.css";

function App() {
  const [clicked, setClicked] = useState(true);

  return (
    <Button variant="contained" onClick={() => setClicked(!clicked)}>
      Column {clicked ? <Add color="primary"/> : <Remove color="secondary"/>}
    </Button>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Answer №4

Store the id of the selected icon in the state of the component and display the icon based on a condition:

import React, { useState } from "react";
import { List, ListItem } from "@material-ui/core";
import AddCircleIcon from "@material-ui/icons/AddCircleOutline";
import BlockIcon from "@material-ui/icons/BlockOutlined";

const UniqueComponent = (props) => {
  const [selectedIconId, setSelectedIconId] = useState(100);

  const handleIconSelection = (iconId) => () => {
    setSelectedIconId(iconId);
  };

  return (
    <List component="nav">
      <ListItem>
        <ListItem button onClick={handleIconSelection(101)}>
          {selectedIconId === 100 ?  <AddCircleIcon /> : <BlockIcon />}
        </ListItem>
      </ListItem>
    </List>
  );
};

export default UniqueComponent;

Answer №5

import "./App.css";
import ThumbUpAltIcon from "@material-ui/icons/ThumbUpAlt";
import React, { useState } from "react";

function App() {
const [heartColor, setHeartColor] = useState("");
const handleHeart = () => {
    const color = heartColor ? "" : "secondary";
    setHeartColor(color);
   };
return (
   <div className="App">
       <ThumbUpAltIcon onClick={handleHeart} color={heartColor}></ThumbUpAltIcon>
   </div>
       );
   }    

export default App;

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

Importing filter function from Material UI to use in the AutoComplete component

Can't figure out if it's a bug or just my lack of understanding in react. No errors displayed, but the filter function isn't working as expected. When I place the function in the same file, the filter works fine. Am I missing something here? ...

Next.js Head component will not repeat the same Meta Tags

In my Next.js project, I have implemented different meta tags with various media targets in the Head section: <Head> <meta name="theme-color" media="(prefers-color-scheme: light)" content="#7f8fa6"/> <meta name= ...

Passing an array of items as a property to a child component in React with Typescript is not possible

In my project, I have multiple classes designed with create-react-app. I am trying to send an array of objects to child components as illustrated below. Items.tsx import * as React from 'react'; import ItemTable from './ItemTable'; imp ...

What is the reason behind FieldSelect returning a string instead of an object like FieldCheckbox?

FieldSelect component from Sharetribe documents is giving me a string, while FieldCheckbox is returning a JSON object. In a specific scenario, I want FieldSelect to store a JSON object. How can I achieve this? Below is the code snippet for reference: I& ...

Is there a way for me to display a customized error message using antd components?

During the registration process using React and Antd, if the backend returns the error message "user already registered" after clicking on "Sign up", it should be displayed in the form. You can customize the display as shown below: An example of how the u ...

Django/React CSRF validation error: Origin verification failed - the URL http://localhost:8000/ does not correspond to any authorized origins

My current project involves the development of a web application using Django, RestApi, and ReactJs. However, I've encountered an error when sending a POST request from a form which reads: "CSRF Failed: Origin checking failed - http://localhost:8000/ ...

What are some methods for singling out a specific table row?

When working on my app, I faced the task of importing a JSON file and displaying its contents in a table with 3 columns. However, there are two main issues that arose: Utilizing array index for the row key is not recommended due to the table also having ...

How to troubleshoot problems with npm, yarn, or package.json

I'm encountering an issue when trying to execute npm start. Can someone help me identify what the problem is? npm ERR! code ENOENT npm ERR! syscall open npm ERR! path C:\Users\john\Desktop\final project\package.json npm ERR! e ...

Steps for incorporating the <head> tag into a dynamically generated client component in Next.js

Struggling to add a title tag to the head of a dynamically rendered client component in next.js. Encountering a Hydration error when attempting to insert the Head tag. 'use client'; import Article from '@/app/components/layouts/Article&apos ...

Troubleshooting a Component File Import Issue in ReactJS

Recently, I've started working with the React Framework and I'm facing an issue. In my Dishdetail.js file, I am trying to render the <Commentform /> component, which should display a button labeled Submit Comment. To avoid clutter, I have i ...

Rotate icon in Material UI Auto Complete when expanding or collapsing

Is there a way to rotate the auto complete icon of material UI when the auto complete component is expanded? Check out this demo of Auto complete: https://codesandbox.io/s/0xx573qrln Your assistance would be highly valued. ...

React Native throws an error when trying to convert a JSON value of type NSNULL, which is '<null>', to a valid URL

Currently, I am working on an app that requires me to access the device photo gallery in order to replace a default image displayed on the screen. The default value is set to null, which seems to work fine on Android but throws an error on iPhone devices. ...

Switch the visibility of a div tag using Next.js

Script export default function Navigation(){ let displayMenu = false; function toggleMenu() { displayMenu = !displayMenu; } return ( <> <button onClick={toggleMenu}>Toggle Navigation</button> {/*This code sh ...

Experiencing difficulties establishing a connection between the React client and Node.js server using SocketIO

I am currently getting familiar with socketIO and have successfully set up a basic nodejs server. However, I am facing an issue where my nextJS app is unable to connect to the server as expected. Despite no errors being displayed, the messages that should ...

Implementing Material-UI Autocomplete: How to Include a Starting Value for the startAdornment

I am using autocomplete with multiple selection permission. https://codesandbox.io/s/bold-jackson-dkjmb?file=/src/App.js In the provided example, there are 3 options for cities. How can I manually insert a value in TextField that is automatically selected ...

The regex routes are now unable to efficiently serve static assets

Question Is it possible to use regex or the built-in URL processor in Express to properly load static files? Expected Behavior Express should match the initial route it encounters and load files as usual. Actual Behavior Error messages indicate that ...

What is the trick to accessing an object's key and value when you are unsure of the object's

Currently, I am in the process of constructing a React component that is designed to receive an array of objects. However, I have encountered a question: Is there a way for me to retrieve both the key and value of an object within the map function without ...

Setting up a middleware file for your nextJs project: A step-by-step guide

Currently, I am deep into a project that involves using Next.js. Progress has been steady so far, but there's a hitch with my middleware.ts file. Despite diligently following the Middleware documentation, it seems like the middleware is not triggering ...

React JS's popup feature can be unreliable, as it tends to break the application frequently

I have been developing a web application that interacts with a public API and presents the retrieved data in a table format. However, I am encountering an issue where clicking the "Click to Display Hottest Planet" button sometimes results in an error. How ...

Customize material-ui button designs using styled-components

I'm currently facing an issue with overriding the border-radius of a material-ui button using styled-components. Despite setting it to 0, it's not taking effect. Here is the code snippet: import React from "react"; import styled from "styled-co ...