Tips for toggling the visibility of an element when a button is clicked in React

In my todo list, I need to display the details of each item when clicked on a button. There are two buttons available: "View Details" and "Hide Details". Below is the code snippet:


        class Todos extends React.Component{
            constructor(props){
                super(props);
                this.state={
                  shown:null,
                  todos: []
                }
            }
        
            showDetails = (todo) => {
                this.setState({
                    shown: todo.id
                });
            }
        
            render(){
                const { shown, todos } = this.state;
                
                return(
                    <div>
                        <ul>
                            {todos.map((todo)=>(
                                <li key={todo.id}>
                                    <span >{todo.title}</span>
                                    
                                     <button onClick={()=>this.showDetails(todo)}>View Details</button>
                                     
                                    {shown === todo.id && (<div>
                                        Description: {todo.description}<br/>
                                        Due Date: {todo.status} <br/>
                                    </div>)  }
                                </li>
                            ))}
                        </ul>
                    </div>
                )
            }
        }
   

The current issue is that clicking on any button shows the details for all todo items. How can I modify the code in order to only display details for the selected todo item?

Answer №1

To enhance the structure and organization of your code, it is suggested to separate each Todo into its own component rather than solely using JSX mapping for each.

const Todo = ({ todo }) => {
  const [visible, setVisbile] = useState(true)

  const toggleDetails = () => {
    setVisbile(!visible)
  }

  return (
    <li key={todo.id}>
      <span >{todo.title}</span>
      <button onClick={toggleDetails}>{ visible ? 'Hide Details' : 'View Details' }</button>
      {visible && (<div>
        Description:{todo.description}<br/>
        Due Date: {todo.status} <br/>
      </div>)  }               
    </li>
  )
}
export default Todo;

If you prefer not to utilize Hooks and instead want to use the class-based approach

class Todo extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      visible: true
    }
  }

  toggleDetails = () => {
    const newToggleState = !this.state.visible
    this.setState({ visible: newToggleState })
  }

  render () {
    const { todo } = this.props
    const { visible } = this.state
    return (
      <li key={todo.id}>
        <span >{todo.title}</span>
        <button onClick={this.toggleDetails}>{ visible ? 'Hide Details' : 'View Details' }</button>
        {visible && (<div>
          Description:{todo.description}<br/>
          Due Date: {todo.status} <br/>
        </div>)  }               
      </li>
    )
  }
}

You can import this into your current component by following this example

render(){
   const { shown, todos } = this.state;
      return(
      <div>
          <ul>
            {todos.map((todo,i)=>(
              <Todo key={todo.id} todo={todo}/>
            ))}
          </ul>
      </div>
      )
  }
}
  

Answer №2

 class Todos extends React.Component{
constructor(props){
    super(props);
    this.state={
      shown:false,
      selectedId:'',
      todos: []
    }
}
showDetails = (isVisible, id) => {
  this.setState({
   shown: isVisible,
   selectedId: id
  });
}

render(){
 const { shown, todos, selectedId } = this.state;
    return(
    <div>
        <ul>
          {todos.map((todo,i)=>(
            <li key={todo.id}>
              <span>{todo.title}</span>
             <button onClick={this.showDetails.bind(this, true, todo.id)}>View Details</button>
             <button onClick={this.showDetails.bind(this, false, todo.id)}>Hide Details</button>

              {shown && selectedId===todo.id && (<div>
                Description:{todo.description}<br/>
                Due Date: {todo.status} <br/>
              </div>)  }               
            </li>
          
          ))}
        </ul>

}

The code includes a method where the specific Todo to be viewed or hidden is controlled by passing its unique id into the function.

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

What could be the reason for the lack of styling on the select element when using PaperProps in the MenuProps of my Select component?

I've been struggling to remove the white padding in this select box for a while now. I've tried countless variations and places to tweak the CSS with no success. Any suggestions on how to make it disappear? The project is using MUI 5, and I even ...

Ways to incorporate a React component to display Google Maps InfoWindows

Here is my code without any external libraries in my React app: import React, { Component } from "react"; import MarkerInfo from "./MarkerInfo"; import { render } from "react-dom"; class Map extends Component { componentDidMount() { this.renderMap(); ...

Creating a unique navigation route in React

My application has a consistent layout for all routes except one, which will be completely different from the rest. The entire application will include a menu, body, footer, etc. However, the one-off route should be standalone without these elements. How ...

Posting data in ASP.NET Core from the frontend to the backend (specifically with React) involves sending information

In my React code, I have a function to hit the API when the submit button is clicked. I update the question and add a new class called httpresponemessage post. const handleOnPreview = (e) => { e.preventDefault(); setsubmittext(text); ...

An issue of "SignatureDoesNotMatch" arises while trying to send an email using Node AWS SDK for the Simple Email Service

I am facing an issue while attempting to send an email using the @aws-sdk/client-ses SDK in Node. The error I encounter is: SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access ...

Trouble with z-index functionality in jQuery datatable

I'm struggling to get the Action Box displayed as an upper layer. I've already tried using z-index but it doesn't seem to make any difference. https://i.stack.imgur.com/rJ1vL.png $(document).ready(function () { ...

What is the best way to access dropdown sub-menu options from a complex multi-level navigation bar

Struggling to figure out how to open my dropdown sub-menu using CSS. Hoping to make it so the user can open it by hovering over the corresponding tag. I attempted to use #lablinksDD to trigger the opening of #ddSbMenu when hovered over #menuDD with #labLin ...

Tips for configuring page-specific variables in Adobe DTM

Although I have integrated Adobe Analytics for tracking on my website, I am facing difficulty in properly defining the variables. This is how I attempted to define the variable: var z = new Object(); z.abc = true; z.def.ghi = true Despite following the ...

What is the process for dynamically updating a variable's state within a render function?

I'm currently working on a project for my class where we are tasked with creating a website using React. Unfortunately, neither myself nor my group members have been able to figure out how to render a function in a variable state and make it dynamic. ...

Using jQuery to iterate over a multi-dimensional array and showing the child elements for each parent array

I am facing an issue with a multidimensional array that contains objects and other arrays. While it is simple to loop through the parent array and display its contents in HTML, I encounter a problem when there are multiple layers of arrays nested within ea ...

Rendering a component six times in React

Currently, I am facing an issue with my custom hook that is used to fetch data from an API. The problem arises when I try to integrate this custom hook into my Context API. The main issue is that the body of the hook keeps getting rendered multiple times ( ...

"Owlcarousel Slider: A beautiful way to showcase

Currently, I am working on a project that involves implementing a slider. Since I lack expertise in JavaScript, I opted to use a plugin called owlcarousel. The challenge I'm encountering relates to the sizing of the container for the items. I'm ...

Is it possible to execute a program on MacOS through a local HTML website?

Are there any straightforward methods to launch Mac programs using HTML? I've created an HTML page featuring a text field and several buttons. The goal is for users to enter a code (numbers) that will then be copied to the clipboard. By clicking on t ...

Is there a way to exclude a specific value from a nested zod scheme?

I'm working with a zod schema where I need to omit certain fields from the schema entirely, instead of just making them optional. Is there a way to achieve this directly in zod? Can fields be omitted or can the schema be preprocessed somehow? For ins ...

Having trouble retrieving react environment variables from process.env?

When developing my React App, I utilized a .env file to securely store some essential API keys. However, as I attempted to access these variables using process.env, I encountered an issue where the values appeared to be set as undefined. To launch the app ...

Display the image in a pop-up window before executing a jQuery script

Lately, I've been focusing on implementing zoom in and zoom out functionality for images. The plugin I've chosen to use is guillotine. It works flawlessly except for one small hiccup. My goal is to integrate it into a website built with angularJ ...

Design that adapts to various screen sizes and devices

I'm facing an issue where the two elements are misaligned on mobile, even though they display perfectly on desktop. In some cases, the bottom element is partially hidden on the left side as shown here: Any suggestions on how to center these elements ...

Is there a way for me to retrieve props that have been passed through the Vue router within a Vue component?

I have configured a route as shown below: { path: 'fit-details', name: 'fit-details', component: Fitment, props: true }, I am passing props via the route using data from the state: this.$router.push({ path: 'fit-details&a ...

Securing a JWT token post login

I am new to NodeJS and despite trying numerous solutions, I am facing a challenge. My project involves NodeJS, MongoDB, Express, and Vanilla JS rendered through Pug with an MVC structure. Issue Current Status: I can successfully log in a user and recei ...

Is there a way to use a less mixin or selector to adjust the position depending on the sibling

Currently, I am working on adjusting the position of multiple sibling divs depending on their order. Although they are all currently set to position: absolute, this may change. Each div is a few hundred pixels tall, but I want them to overlap in such a wa ...