Assign the class name of the clicked div to another specific div

I am working on a function component where I want to append a class name to a specific div when a user clicks on one of 4 different divs. The divs are named note_b, note_g, note_p, and note_y.

Below is the code snippet that I have so far:

import React from 'react-dom';
import DraggableCore from 'react-draggable';

function Note(props) {
    return (
        <DraggableCore defaultPosition={{x: 1000, y: 200}}>
            <div className={"note " + }>
                <div id="note_head">
                    <div id="note_bin"></div>
                    <div className="note_b" onClick={}></div>
                    <div className="note_p" onClick={}></div>
                    <div className="note_g" onClick={}></div>
                    <div className="note_y" onClick={}></div>
                    <div id="note_exit"></div>
                </div>
                <p>
                    {props.message}
                </p>
            </div>
        </DraggableCore>
    )
}

export default Note;

Answer №1

Big thanks to @Andy for the guidance! After revisiting state hooks, I managed to come up with the following solution:

import React, { useState }  from 'react';
import DraggableCore from 'react-draggable';

function NoteComponent(props) {
    const [background, setBackground] = useState('note_bg_b');

    return (
        <DraggableCore defaultPosition={{x: 1000, y: 200}}>
            <div className={"note " + background}>
                <div id="note_head">
                    <div id="note_bin"></div>
                    <div className="note_b" onClick={() => setBackground('note_b')}></div>
                    <div className="note_p" onClick={() => setBackground('note_b')}></div>
                    <div className="note_g" onClick={() => setBackground('note_b')}></div>
                    <div className="note_y" onClick={() => setBackground('note_b')}></div>
                    <div id="note_exit"></div>
                </div>
                <p>
                    {props.message}
                </p>
            </div>
        </DraggableCore>
    )
}

export default NoteComponent;

A cleaner and more efficient approach might exist for this task. Nevertheless, the current implementation is fully functional.

Answer №2

Implement the onClick event handler for each of the four divs and assign the clicked className to the note div.

UPDATE for another query: To avoid removing the added className when clicking inside the note div, utilize an event listener to determine the origin of the click. If it doesn't originate from an element with the classes note_b, note_p, note_g, or note_y, then do not remove the className.

import React, { useState, useRef } from 'react';
import DraggableCore from 'react-draggable';

function Note(props) {
    const [className, setClassName] = useState('');
    const noteDiv = useRef(null);

    const handleClick = e => {
        setClassName(e.target.className);
    }

    //This function prevents the default event action from occurring when the page is unloaded. 
    //If the target element of the event does not have one of the specified class names, it removes the class from the element with the class "note".    
    const handleUnload = e => {
        e.preventDefault();
        const noteDiv = document.querySelector('.note');
        if (!['.note', 'note_b', 'note_p', 'note_g', 'note_y'].includes(e.target.className)) {
            noteDiv.classList.remove(e.target.className);
        }
    }

    return (
        <DraggableCore defaultPosition={{ x: 1000, y: 200 }}>
            <div ref={noteDiv} className={`note ${className}`} onClick={handleUnload}>
                <div id="note_head">
                    <div id="note_bin"></div>
                    <div className="note_b" onClick={handleClick}></div>
                    <div className="note_p" onClick={handleClick}></div>
                    <div className="note_g" onClick={handleClick}></div>
                    <div className="note_y" onClick={handleClick}></div>
                    <div id="note_exit"></div>
                </div>
                <p>
                    {props.message}
                </p>
            </div>
        </DraggableCore>
    )
}

export default Note;
    

Answer №3

If you want to improve your class organization and enhance the identification of each note, consider incorporating data attributes for each note.

Instead of using a className like node_b, opt for two separate classes: note b. The class "note" can serve as a general identifier for all notes, while "b" can specify a particular note. Different colors can be used to differentiate between them clearly.

By adding the data attribute, you make it simpler to distinguish each note within the code. This enables you to extract the note id from the dataset of the clicked element in the click handler, set the state accordingly, and utilize that state in the parent element.

Note: To implement event delegation, only one click handler is employed on the container element of the notes.

const { useState } = React;

function Note({ message }) {

  // Initialize a new state to store the note id
  const [ noteClass, setNoteClass ] = useState('');

  // The handler checks if the clicked element is a "note" element,
  // extracts the note id from the element's dataset, and sets the state accordingly
  function handleClick(e) {
    if (e.target.matches('.note')) {
      const { note } = e.target.dataset;
      setNoteClass(note);
    }
  }

  // When the state changes, the containing element's class also updates      
  return (
    <div className={noteClass}>
      <div id="note_head">
        <div id="note_bin" onClick={handleClick}>
          <div data-note="b" className="note b">B</div>
          <div data-note="p" className="note p">P</div>
          <div data-note="g" className="note g">G</div>
          <div data-note="y" className="note y">Y</div>
        </div>
        <p>{message}</p>
      </div>
    </div>
  );

}

ReactDOM.render(
  <Note message="Message" />,
  document.getElementById('react')
);
.note { padding: 0.25em; border: 1px solid #4444; }
.note:not(:last-child) { margin-bottom: 0.25em; }
.note:hover { background-color: #fffff0; cursor: pointer; }
.b { color: red; }
.p { color: blue; }
.g { color: green; }
.y { color: gray; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

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

Having trouble setting up my Vuex store from localStorage for authentication in Nuxt

I have been working with Nuxt.js and have been trying to create my own authentication system. Everything seems to be functioning correctly, but whenever I refresh the page, the state reverts back to its initial data. To address this issue, I attempted to i ...

React conditional rendering with IF-ELSE allows for dynamic content loading on the page

Currently, I am utilizing React and attempting to navigate to a different route using the <Link> component. The issue I am facing is that when I click on the link, it triggers an actual page load rather than performing a single-page application (SPA ...

Coldfusion: The Troubles of an Empty Link href="#" Error

For my CFWheels Coldfusion project, I have been utilizing Adobe Coldfusion Builder 3. In Coldfusion, when you want to output a variable, you typically do something like this: #variable_name# However, I am interested in incorporating an empty link into m ...

Having trouble with my Angular application, seems to be stuck at the loading screen. Not sure what's causing it, possibly

Hey there, I'm hoping to create a straightforward app that showcases posts. However, I've encountered an issue when deploying the initial page which is stuck on "Loading...". I believe it's a minor problem and would appreciate your assistan ...

The menu field remains open even after clicking on the menu

I have encountered an issue with my code. Here is a DEMO that I created on jsfiddle.net Currently, when you click on the red div, the menu opens. However, if you click on the menu items, the menu area does not close. What do I need to do in order to clo ...

EmberJS: Learning how to create a record with a belongsTo relationship

My issue involves using Posts and Comments to explain my problem. In my post_controller, I am trying to create a new record for a comment related to the current post. What is the recommended way to achieve this in Ember? The relationship between Post and ...

Modify only unprocessed text within the HTML content

Consider the following string: html_string = '<span><span class=\"ip\"></span> Do not stare <span class=\"img\"></span> at the monitor continuously </span>\r\n' I am looking to ...

Electron experiences a crash while attempting to execute an HTTPS request within an addeventlistener callback function

In the process of creating a simple Electron application that facilitates user login into a system, I encounter an issue. The app collects the username and password entered by the user through form text inputs. Upon clicking the "login" button, the program ...

Using a React button to sort through an array

Hey there, I'm currently working on an app that filters a list based on user input. The idea is to click on buttons to exclude users with specific letters in their names. However, the code I have right now isn't functioning properly. Any assistan ...

Editing input within a Bootstrap 4 popover causes it to lose focus

I am using Bootstrap 4 along with the Bootstrap colorpicker to implement a colorpicker within a popup that includes an input field for setting the color code. However, I am facing an issue where the input field (#color-value) seems uneditable when the popo ...

Utilizing jQuery to configure multiple selection options within OptGroup elements

I am working with a Multi-Select list that has OptGroups set up in the following way: <select multiple="multiple" id="idCountry"> <optgroup label="ASIA"> <option value="AUSTRALIA">AUSTRALIA</option> <option value ...

Loading HTML content in a WPF WebBrowser without encountering security messages

Currently, I am developing a WPF application in which I create the content of an HTML file as a string (including some JavaScript functions for calculations). After generating the string, I save it as an HTML file on my local disk and then reload it using ...

AngularJS uses variables defined by using curly braces like {{"message"}}

I am currently utilizing the following code snippet to monitor route changes: $scope.$on('$routeChangeStart', function (event, toState, toParams, fromState, fromParams) { //content $log.log(toState); } Whenever I print out "toState ...

To utilize this.<module> within a Nuxt plugin, simply access it

How can I access a JS API exposed by a Nuxt module from a client-side plugin? Situation: I am utilizing Buefy/Bulma, which is implemented in nuxt.config.js like this: modules: [ ['nuxt-buefy', {css: false}], ], Buefy provides this.$buefy.&l ...

Struggling with continuously re-rendering a color background when using useMemo in React?

After every re-render, a new color is generated. Is there a way to store the initial color and reuse it in subsequent renders? const initialColor = generateNewColor(); // some random color const backgroundColor = React.useMemo(() => { return ...

Obtaining the innerHTML value using JavaScript in an Asp.net Core 5 View

Apologies for any inaccuracies in my English writing. In the Asp.Net Core project view, I am trying to use JavaScript to capture multiple Span tags within innerHTML represented by a loop and display their sum in another tag. However, I am only able to ret ...

Load charts.js synchronously into a div using XMLHttpRequest

At the moment, there is a menu displayed on the left side of the page. When you click on the navigation links, the page content loads using the code snippet below: if (this.id == "view-charts") { $("#rightContainer").load("view-charts.php"); $(thi ...

Utilizing jQuery for animating SVG elements with dynamic color changes and scaling effects upon hover

Seeking assistance from coding experts! I have created an icon and am attempting to modify it so that the color changes when hovered over. Additionally, I want the white square to scale down by 50% starting from the top-left corner of its current position. ...

Do you have any tips on designing a mobile-friendly navigation bar?

Struggling with creating a responsive navbar using Bootstrap 5? The navbar-brand is causing issues with letters overflowing over other elements, and the toggle-icon is not aligning properly. Check out my Codepen for reference: https://codepen.io/namename12 ...

Switching Languages in react-simple-keyboard: Explained

import React, { useRef, useState } from "react"; import Keyboard from "react-simple-keyboard"; import "react-simple-keyboard/build/css/index.css"; function App() { const [input, setInput] = useState(""); const [ ...